WebView.cpp revision 829229abf10ddf6135c682d42a291925ef0da35f
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, SkRegion& inval, bool showVisualIndicator, 525 bool isPictureAfterFirstLayout) 526{ 527 bool queueFull = false; 528#if USE(ACCELERATED_COMPOSITING) 529 if (m_glWebViewState) { 530 // TODO: mark as inval on webkit side 531 if (newBaseLayer) 532 newBaseLayer->markAsDirty(inval); 533 queueFull = m_glWebViewState->setBaseLayer(newBaseLayer, showVisualIndicator, 534 isPictureAfterFirstLayout); 535 } 536#endif 537 538#if ENABLE(ANDROID_OVERFLOW_SCROLL) 539 if (newBaseLayer) { 540 // TODO: the below tree position copies are only necessary in software rendering 541 copyScrollPositionRecursive(m_baseLayer, newBaseLayer); 542 } 543#endif 544 SkSafeUnref(m_baseLayer); 545 m_baseLayer = newBaseLayer; 546 547 return queueFull; 548} 549 550void replaceBaseContent(PictureSet* set) 551{ 552 if (!m_baseLayer) 553 return; 554 // TODO: remove the split picture codepath 555 delete set; 556} 557 558void copyBaseContentToPicture(SkPicture* picture) 559{ 560 if (!m_baseLayer) 561 return; 562 LayerContent* content = m_baseLayer->content(); 563 content->draw(picture->beginRecording(content->width(), content->height(), 564 SkPicture::kUsePathBoundsForClip_RecordingFlag)); 565 picture->endRecording(); 566} 567 568bool hasContent() { 569 if (!m_baseLayer) 570 return false; 571 return !m_baseLayer->content()->isEmpty(); 572} 573 574void setFunctor(Functor* functor) { 575 delete m_glDrawFunctor; 576 m_glDrawFunctor = functor; 577} 578 579Functor* getFunctor() { 580 return m_glDrawFunctor; 581} 582 583void setVisibleRect(SkRect& visibleRect) { 584 m_visibleRect = visibleRect; 585} 586 587void setDrawExtra(DrawExtra *extra, DrawExtras type) 588{ 589 if (type == DrawExtrasNone) 590 return; 591 DrawExtra* old = m_extras[type - 1]; 592 m_extras[type - 1] = extra; 593 if (old != extra) { 594 delete old; 595 } 596} 597 598void setTextSelection(SelectText *selection) { 599 setDrawExtra(selection, DrawExtrasSelection); 600} 601 602const TransformationMatrix* getLayerTransform(int layerId) { 603 if (layerId != -1 && m_baseLayer) { 604 LayerAndroid* layer = m_baseLayer->findById(layerId); 605 // We need to make sure the drawTransform is up to date as this is 606 // called before a draw() or drawGL() 607 if (layer) { 608 m_baseLayer->updateLayerPositions(m_visibleRect); 609 return layer->drawTransform(); 610 } 611 } 612 return 0; 613} 614 615int getHandleLayerId(SelectText::HandleId handleId, SkIPoint& cursorPoint, 616 FloatQuad& textBounds) { 617 SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection)); 618 if (!selectText || !m_baseLayer) 619 return -1; 620 int layerId = selectText->caretLayerId(handleId); 621 IntRect cursorRect = selectText->caretRect(handleId); 622 IntRect textRect = selectText->textRect(handleId); 623 // Rects exclude the last pixel on right/bottom. We want only included pixels. 624 cursorPoint.set(cursorRect.x(), cursorRect.maxY() - 1); 625 textRect.setHeight(std::max(1, textRect.height() - 1)); 626 textRect.setWidth(std::max(1, textRect.width() - 1)); 627 textBounds = FloatQuad(textRect); 628 629 const TransformationMatrix* transform = getLayerTransform(layerId); 630 if (transform) { 631 // We're overloading the concept of Rect to be just the two 632 // points (bottom-left and top-right. 633 cursorPoint = transform->mapPoint(cursorPoint); 634 textBounds = transform->mapQuad(textBounds); 635 } 636 return layerId; 637} 638 639void mapLayerRect(int layerId, SkIRect& rect) { 640 const TransformationMatrix* transform = getLayerTransform(layerId); 641 if (transform) 642 transform->mapRect(rect); 643} 644 645void floatQuadToQuadF(JNIEnv* env, const FloatQuad& nativeTextQuad, 646 jobject textQuad) 647{ 648 jobject p1 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP1); 649 jobject p2 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP2); 650 jobject p3 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP3); 651 jobject p4 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP4); 652 GraphicsJNI::point_to_jpointf(nativeTextQuad.p1(), env, p1); 653 GraphicsJNI::point_to_jpointf(nativeTextQuad.p2(), env, p2); 654 GraphicsJNI::point_to_jpointf(nativeTextQuad.p3(), env, p3); 655 GraphicsJNI::point_to_jpointf(nativeTextQuad.p4(), env, p4); 656 env->DeleteLocalRef(p1); 657 env->DeleteLocalRef(p2); 658 env->DeleteLocalRef(p3); 659 env->DeleteLocalRef(p4); 660} 661 662// This is called when WebView switches rendering modes in a more permanent fashion 663// such as when the layer type is set or the view is attached/detached from the window 664int setHwAccelerated(bool hwAccelerated) { 665 if (!m_glWebViewState) 666 return 0; 667 LayerAndroid* root = m_baseLayer; 668 if (root) 669 return root->setHwAccelerated(hwAccelerated); 670 return 0; 671} 672 673 bool m_isDrawingPaused; 674private: // local state for WebView 675 // private to getFrameCache(); other functions operate in a different thread 676 WebViewCore* m_viewImpl; 677 int m_generation; // associate unique ID with sent kit focus to match with ui 678 // Corresponds to the same-named boolean on the java side. 679 bool m_heightCanMeasure; 680 int m_lastDx; 681 SkMSec m_lastDxTime; 682 DrawExtra* m_extras[DRAW_EXTRAS_SIZE]; 683 BaseLayerAndroid* m_baseLayer; 684 Functor* m_glDrawFunctor; 685#if USE(ACCELERATED_COMPOSITING) 686 GLWebViewState* m_glWebViewState; 687#endif 688 SkRect m_visibleRect; 689 bool m_isHighEndGfx; 690}; // end of WebView class 691 692 693/** 694 * This class holds a function pointer and parameters for calling drawGL into a specific 695 * viewport. The pointer to the Functor will be put on a framework display list to be called 696 * when the display list is replayed. 697 */ 698class GLDrawFunctor : Functor { 699 public: 700 GLDrawFunctor(WebView* _wvInstance, 701 int (WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*, 702 WebCore::IntRect&, int, WebCore::IntRect&, jfloat, jint, bool), 703 WebCore::IntRect _viewRect, float _scale, int _extras) { 704 wvInstance = _wvInstance; 705 funcPtr = _funcPtr; 706 viewRect = _viewRect; 707 scale = _scale; 708 extras = _extras; 709 }; 710 status_t operator()(int messageId, void* data) { 711 TRACE_METHOD(); 712 713 if (viewRect.isEmpty()) { 714 // NOOP operation if viewport is empty 715 return 0; 716 } 717 718 WebCore::IntRect inval; 719 int titlebarHeight = webViewRect.height() - viewRect.height(); 720 721 uirenderer::DrawGlInfo* info = reinterpret_cast<uirenderer::DrawGlInfo*>(data); 722 WebCore::IntRect clip(info->clipLeft, info->clipTop, 723 info->clipRight - info->clipLeft, 724 info->clipBottom - info->clipTop); 725 726 WebCore::IntRect localViewRect = viewRect; 727 if (info->isLayer) { 728 // When webview is on a layer, we need to use the viewport relative 729 // to the FBO, rather than the screen(which will use viewRect). 730 localViewRect.setX(clip.x()); 731 localViewRect.setY(info->height - clip.y() - clip.height()); 732 } 733 bool shouldDraw = (messageId == uirenderer::DrawGlInfo::kModeDraw); 734 // Send the necessary info to the shader. 735 TilesManager::instance()->shader()->setGLDrawInfo(info); 736 737 int returnFlags = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect, 738 titlebarHeight, clip, scale, extras, shouldDraw); 739 if ((returnFlags & uirenderer::DrawGlInfo::kStatusDraw) != 0) { 740 IntRect finalInval; 741 if (inval.isEmpty()) 742 finalInval = webViewRect; 743 else { 744 finalInval.setX(webViewRect.x() + inval.x()); 745 finalInval.setY(webViewRect.y() + titlebarHeight + inval.y()); 746 finalInval.setWidth(inval.width()); 747 finalInval.setHeight(inval.height()); 748 } 749 info->dirtyLeft = finalInval.x(); 750 info->dirtyTop = finalInval.y(); 751 info->dirtyRight = finalInval.maxX(); 752 info->dirtyBottom = finalInval.maxY(); 753 } 754 // return 1 if invalidation needed, 2 to request non-drawing functor callback, 0 otherwise 755 ALOGV("returnFlags are %d, shouldDraw %d", returnFlags, shouldDraw); 756 return returnFlags; 757 } 758 void updateRect(WebCore::IntRect& _viewRect) { 759 viewRect = _viewRect; 760 } 761 void updateViewRect(WebCore::IntRect& _viewRect) { 762 webViewRect = _viewRect; 763 } 764 void updateScale(float _scale) { 765 scale = _scale; 766 } 767 private: 768 WebView* wvInstance; 769 int (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*, 770 WebCore::IntRect&, int, WebCore::IntRect&, float, int, bool); 771 WebCore::IntRect viewRect; 772 WebCore::IntRect webViewRect; 773 jfloat scale; 774 jint extras; 775}; 776 777/* 778 * Native JNI methods 779 */ 780 781static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl, 782 jstring drawableDir, jboolean isHighEndGfx) 783{ 784 WTF::String dir = jstringToWtfString(env, drawableDir); 785 new WebView(env, obj, viewImpl, dir, isHighEndGfx); 786 // NEED THIS OR SOMETHING LIKE IT! 787 //Release(obj); 788} 789 790static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj) 791{ 792 if (obj) { 793 int L, T, R, B; 794 GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B); 795 return WebCore::IntRect(L, T, R - L, B - T); 796 } else 797 return WebCore::IntRect(); 798} 799 800static SkRect jrectf_to_rect(JNIEnv* env, jobject obj) 801{ 802 SkRect rect = SkRect::MakeEmpty(); 803 if (obj) 804 GraphicsJNI::jrectf_to_rect(env, obj, &rect); 805 return rect; 806} 807 808static jint nativeDraw(JNIEnv *env, jobject obj, jobject canv, 809 jobject visible, jint color, 810 jint extras, jboolean split) { 811 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); 812 WebView* webView = GET_NATIVE_VIEW(env, obj); 813 SkRect visibleRect = jrectf_to_rect(env, visible); 814 webView->setVisibleRect(visibleRect); 815 PictureSet* pictureSet = webView->draw(canvas, color, 816 static_cast<WebView::DrawExtras>(extras), split); 817 return reinterpret_cast<jint>(pictureSet); 818} 819 820static jint nativeCreateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView, 821 jobject jrect, jobject jviewrect, 822 jobject jvisiblerect, 823 jfloat scale, jint extras) { 824 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); 825 WebView *wvInstance = (WebView*) nativeView; 826 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect); 827 wvInstance->setVisibleRect(visibleRect); 828 829 GLDrawFunctor* functor = new GLDrawFunctor(wvInstance, 830 &android::WebView::drawGL, viewRect, scale, extras); 831 wvInstance->setFunctor((Functor*) functor); 832 833 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect); 834 functor->updateViewRect(webViewRect); 835 836 return (jint)functor; 837} 838 839static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView) { 840 WebView *wvInstance = (WebView*) nativeView; 841 if (!wvInstance) 842 return 0; 843 844 return (jint) wvInstance->getFunctor(); 845} 846 847static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView, jobject jrect, 848 jobject jviewrect, jobject jvisiblerect, jfloat scale) { 849 WebView *wvInstance = (WebView*) nativeView; 850 if (wvInstance) { 851 GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor(); 852 if (functor) { 853 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); 854 functor->updateRect(viewRect); 855 856 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect); 857 wvInstance->setVisibleRect(visibleRect); 858 859 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect); 860 functor->updateViewRect(webViewRect); 861 862 functor->updateScale(scale); 863 } 864 } 865} 866 867static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint nativeView) 868{ 869 // only call in software rendering, initialize and evaluate animations 870#if USE(ACCELERATED_COMPOSITING) 871 BaseLayerAndroid* baseLayer = ((WebView*)nativeView)->getBaseLayer(); 872 if (baseLayer) { 873 baseLayer->initAnimations(); 874 return baseLayer->evaluateAnimations(); 875 } 876#endif 877 return false; 878} 879 880static bool nativeSetBaseLayer(JNIEnv *env, jobject obj, jint nativeView, jint layer, jobject inval, 881 jboolean showVisualIndicator, 882 jboolean isPictureAfterFirstLayout) 883{ 884 BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer); 885 SkRegion invalRegion; 886 if (inval) 887 invalRegion = *GraphicsJNI::getNativeRegion(env, inval); 888 return ((WebView*)nativeView)->setBaseLayer(layerImpl, invalRegion, showVisualIndicator, 889 isPictureAfterFirstLayout); 890} 891 892static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj) 893{ 894 return GET_NATIVE_VIEW(env, obj)->getBaseLayer(); 895} 896 897static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content) 898{ 899 PictureSet* set = reinterpret_cast<PictureSet*>(content); 900 GET_NATIVE_VIEW(env, obj)->replaceBaseContent(set); 901} 902 903static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pict) 904{ 905 SkPicture* picture = GraphicsJNI::getNativePicture(env, pict); 906 GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture); 907} 908 909static bool nativeHasContent(JNIEnv *env, jobject obj) 910{ 911 return GET_NATIVE_VIEW(env, obj)->hasContent(); 912} 913 914static jobject nativeLayerBounds(JNIEnv* env, jobject obj, jint jlayer) 915{ 916 SkRect r; 917#if USE(ACCELERATED_COMPOSITING) 918 LayerAndroid* layer = (LayerAndroid*) jlayer; 919 r = layer->bounds(); 920#else 921 r.setEmpty(); 922#endif 923 SkIRect irect; 924 r.round(&irect); 925 jclass rectClass = env->FindClass("android/graphics/Rect"); 926 jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V"); 927 jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop, 928 irect.fRight, irect.fBottom); 929 env->DeleteLocalRef(rectClass); 930 return rect; 931} 932 933static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure) 934{ 935 WebView* view = GET_NATIVE_VIEW(env, obj); 936 ALOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure"); 937 view->setHeightCanMeasure(measure); 938} 939 940static void nativeDestroy(JNIEnv *env, jobject obj) 941{ 942 WebView* view = GET_NATIVE_VIEW(env, obj); 943 ALOGD("nativeDestroy view: %p", view); 944 ALOG_ASSERT(view, "view not set in nativeDestroy"); 945 delete view; 946} 947 948static void nativeStopGL(JNIEnv *env, jobject obj) 949{ 950 GET_NATIVE_VIEW(env, obj)->stopGL(); 951} 952 953static jobject nativeGetSelection(JNIEnv *env, jobject obj) 954{ 955 WebView* view = GET_NATIVE_VIEW(env, obj); 956 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 957 String selection = view->getSelection(); 958 return wtfStringToJstring(env, selection); 959} 960 961static void nativeDiscardAllTextures(JNIEnv *env, jobject obj) 962{ 963 //discard all textures for debugging/test purposes, but not gl backing memory 964 bool allTextures = true, deleteGLTextures = false; 965 TilesManager::instance()->discardTextures(allTextures, deleteGLTextures); 966} 967 968static void nativeTileProfilingStart(JNIEnv *env, jobject obj) 969{ 970 TilesManager::instance()->getProfiler()->start(); 971} 972 973static float nativeTileProfilingStop(JNIEnv *env, jobject obj) 974{ 975 return TilesManager::instance()->getProfiler()->stop(); 976} 977 978static void nativeTileProfilingClear(JNIEnv *env, jobject obj) 979{ 980 TilesManager::instance()->getProfiler()->clear(); 981} 982 983static int nativeTileProfilingNumFrames(JNIEnv *env, jobject obj) 984{ 985 return TilesManager::instance()->getProfiler()->numFrames(); 986} 987 988static int nativeTileProfilingNumTilesInFrame(JNIEnv *env, jobject obj, int frame) 989{ 990 return TilesManager::instance()->getProfiler()->numTilesInFrame(frame); 991} 992 993static int nativeTileProfilingGetInt(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey) 994{ 995 WTF::String key = jstringToWtfString(env, jkey); 996 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile); 997 998 if (key == "left") 999 return record->left; 1000 if (key == "top") 1001 return record->top; 1002 if (key == "right") 1003 return record->right; 1004 if (key == "bottom") 1005 return record->bottom; 1006 if (key == "level") 1007 return record->level; 1008 if (key == "isReady") 1009 return record->isReady ? 1 : 0; 1010 return -1; 1011} 1012 1013static float nativeTileProfilingGetFloat(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey) 1014{ 1015 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile); 1016 return record->scale; 1017} 1018 1019#ifdef ANDROID_DUMP_DISPLAY_TREE 1020static void dumpToFile(const char text[], void* file) { 1021 fwrite(text, 1, strlen(text), reinterpret_cast<FILE*>(file)); 1022 fwrite("\n", 1, 1, reinterpret_cast<FILE*>(file)); 1023} 1024#endif 1025 1026// Return true to view invalidate WebView 1027static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jvalue) 1028{ 1029 WTF::String key = jstringToWtfString(env, jkey); 1030 WTF::String value = jstringToWtfString(env, jvalue); 1031 if (key == "inverted") { 1032 bool shouldInvert = (value == "true"); 1033 TilesManager::instance()->setInvertedScreen(shouldInvert); 1034 return true; 1035 } 1036 else if (key == "inverted_contrast") { 1037 float contrast = value.toFloat(); 1038 TilesManager::instance()->setInvertedScreenContrast(contrast); 1039 return true; 1040 } 1041 else if (key == "enable_cpu_upload_path") { 1042 TilesManager::instance()->transferQueue()->setTextureUploadType( 1043 value == "true" ? CpuUpload : GpuUpload); 1044 } 1045 else if (key == "use_minimal_memory") { 1046 TilesManager::instance()->setUseMinimalMemory(value == "true"); 1047 } 1048 else if (key == "use_double_buffering") { 1049 TilesManager::instance()->setUseDoubleBuffering(value == "true"); 1050 } 1051 else if (key == "tree_updates") { 1052 TilesManager::instance()->clearContentUpdates(); 1053 } 1054 return false; 1055} 1056 1057static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring jkey) 1058{ 1059 WTF::String key = jstringToWtfString(env, jkey); 1060 if (key == "tree_updates") { 1061 int updates = TilesManager::instance()->getContentUpdates(); 1062 WTF::String wtfUpdates = WTF::String::number(updates); 1063 return wtfStringToJstring(env, wtfUpdates); 1064 } 1065 return 0; 1066} 1067 1068static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level) 1069{ 1070 if (TilesManager::hardwareAccelerationEnabled()) { 1071 // When we got TRIM_MEMORY_MODERATE or TRIM_MEMORY_COMPLETE, we should 1072 // make sure the transfer queue is empty and then abandon the Surface 1073 // Texture to avoid ANR b/c framework may destroy the EGL context. 1074 // Refer to WindowManagerImpl.java for conditions we followed. 1075 TilesManager* tilesManager = TilesManager::instance(); 1076 if ((level >= TRIM_MEMORY_MODERATE 1077 && !tilesManager->highEndGfx()) 1078 || level >= TRIM_MEMORY_COMPLETE) { 1079 ALOGD("OnTrimMemory with EGL Context %p", eglGetCurrentContext()); 1080 tilesManager->cleanupGLResources(); 1081 } 1082 1083 bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true; 1084 tilesManager->discardTextures(freeAllTextures, glTextures); 1085 } 1086} 1087 1088static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl) 1089{ 1090#ifdef ANDROID_DUMP_DISPLAY_TREE 1091 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1092 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1093 1094 if (view && view->getWebViewCore()) { 1095 FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w"); 1096 if (file) { 1097 SkFormatDumper dumper(dumpToFile, file); 1098 // dump the URL 1099 if (jurl) { 1100 const char* str = env->GetStringUTFChars(jurl, 0); 1101 SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE); 1102 dumpToFile(str, file); 1103 env->ReleaseStringUTFChars(jurl, str); 1104 } 1105 // now dump the display tree 1106 SkDumpCanvas canvas(&dumper); 1107 // this will playback the picture into the canvas, which will 1108 // spew its contents to the dumper 1109 view->draw(&canvas, 0, WebView::DrawExtrasNone, false); 1110 // we're done with the file now 1111 fwrite("\n", 1, 1, file); 1112 fclose(file); 1113 } 1114#if USE(ACCELERATED_COMPOSITING) 1115 const LayerAndroid* baseLayer = view->getBaseLayer(); 1116 if (baseLayer) { 1117 FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w"); 1118 if (file) { 1119 baseLayer->dumpLayers(file, 0); 1120 fclose(file); 1121 } 1122 } 1123#endif 1124 } 1125#endif 1126} 1127 1128static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint x, jint y, 1129 jobject rect, jobject bounds) 1130{ 1131 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1132 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1133 SkIRect nativeRect, nativeBounds; 1134 int id = view->scrollableLayer(x, y, &nativeRect, &nativeBounds); 1135 if (rect) 1136 GraphicsJNI::irect_to_jrect(nativeRect, env, rect); 1137 if (bounds) 1138 GraphicsJNI::irect_to_jrect(nativeBounds, env, bounds); 1139 return id; 1140} 1141 1142static bool nativeScrollLayer(JNIEnv* env, jobject obj, jint layerId, jint x, 1143 jint y) 1144{ 1145#if ENABLE(ANDROID_OVERFLOW_SCROLL) 1146 WebView* view = GET_NATIVE_VIEW(env, obj); 1147 view->scrollLayer(layerId, x, y); 1148 1149 //TODO: the below only needed for the SW rendering path 1150 LayerAndroid* baseLayer = view->getBaseLayer(); 1151 if (!baseLayer) 1152 return false; 1153 LayerAndroid* layer = baseLayer->findById(layerId); 1154 if (!layer || !layer->contentIsScrollable()) 1155 return false; 1156 return static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); 1157#endif 1158 return false; 1159} 1160 1161static void nativeSetIsScrolling(JNIEnv* env, jobject jwebview, jboolean isScrolling) 1162{ 1163 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1164 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1165 view->setIsScrolling(isScrolling); 1166} 1167 1168static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled) 1169{ 1170 BaseRenderer::setCurrentRendererType(enabled ? BaseRenderer::Ganesh : BaseRenderer::Raster); 1171} 1172 1173static int nativeGetBackgroundColor(JNIEnv* env, jobject obj) 1174{ 1175 WebView* view = GET_NATIVE_VIEW(env, obj); 1176 BaseLayerAndroid* baseLayer = view->getBaseLayer(); 1177 if (baseLayer) { 1178 WebCore::Color color = baseLayer->getBackgroundColor(); 1179 if (color.isValid()) 1180 return SkColorSetARGB(color.alpha(), color.red(), 1181 color.green(), color.blue()); 1182 } 1183 return SK_ColorWHITE; 1184} 1185 1186static void nativeSetPauseDrawing(JNIEnv *env, jobject obj, jint nativeView, 1187 jboolean pause) 1188{ 1189 ((WebView*)nativeView)->m_isDrawingPaused = pause; 1190} 1191 1192static void nativeSetTextSelection(JNIEnv *env, jobject obj, jint nativeView, 1193 jint selectionPtr) 1194{ 1195 SelectText* selection = reinterpret_cast<SelectText*>(selectionPtr); 1196 reinterpret_cast<WebView*>(nativeView)->setTextSelection(selection); 1197} 1198 1199static jint nativeGetHandleLayerId(JNIEnv *env, jobject obj, jint nativeView, 1200 jint handleIndex, jobject cursorPoint, 1201 jobject textQuad) 1202{ 1203 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1204 SkIPoint nativePoint; 1205 FloatQuad nativeTextQuad; 1206 int layerId = webview->getHandleLayerId((SelectText::HandleId) handleIndex, 1207 nativePoint, nativeTextQuad); 1208 if (cursorPoint) 1209 GraphicsJNI::ipoint_to_jpoint(nativePoint, env, cursorPoint); 1210 if (textQuad) 1211 webview->floatQuadToQuadF(env, nativeTextQuad, textQuad); 1212 return layerId; 1213} 1214 1215static jboolean nativeIsBaseFirst(JNIEnv *env, jobject obj, jint nativeView) 1216{ 1217 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1218 SelectText* select = static_cast<SelectText*>( 1219 webview->getDrawExtra(WebView::DrawExtrasSelection)); 1220 return select ? select->isBaseFirst() : false; 1221} 1222 1223static void nativeMapLayerRect(JNIEnv *env, jobject obj, jint nativeView, 1224 jint layerId, jobject rect) 1225{ 1226 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1227 SkIRect nativeRect; 1228 GraphicsJNI::jrect_to_irect(env, rect, &nativeRect); 1229 webview->mapLayerRect(layerId, nativeRect); 1230 GraphicsJNI::irect_to_jrect(nativeRect, env, rect); 1231} 1232 1233static jint nativeSetHwAccelerated(JNIEnv *env, jobject obj, jint nativeView, 1234 jboolean hwAccelerated) 1235{ 1236 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1237 return webview->setHwAccelerated(hwAccelerated); 1238} 1239 1240/* 1241 * JNI registration 1242 */ 1243static JNINativeMethod gJavaWebViewMethods[] = { 1244 { "nativeCreate", "(ILjava/lang/String;Z)V", 1245 (void*) nativeCreate }, 1246 { "nativeDestroy", "()V", 1247 (void*) nativeDestroy }, 1248 { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;IIZ)I", 1249 (void*) nativeDraw }, 1250 { "nativeCreateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I", 1251 (void*) nativeCreateDrawGLFunction }, 1252 { "nativeGetDrawGLFunction", "(I)I", 1253 (void*) nativeGetDrawGLFunction }, 1254 { "nativeUpdateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;F)V", 1255 (void*) nativeUpdateDrawGLFunction }, 1256 { "nativeDumpDisplayTree", "(Ljava/lang/String;)V", 1257 (void*) nativeDumpDisplayTree }, 1258 { "nativeEvaluateLayersAnimations", "(I)Z", 1259 (void*) nativeEvaluateLayersAnimations }, 1260 { "nativeGetSelection", "()Ljava/lang/String;", 1261 (void*) nativeGetSelection }, 1262 { "nativeLayerBounds", "(I)Landroid/graphics/Rect;", 1263 (void*) nativeLayerBounds }, 1264 { "nativeSetHeightCanMeasure", "(Z)V", 1265 (void*) nativeSetHeightCanMeasure }, 1266 { "nativeSetBaseLayer", "(IILandroid/graphics/Region;ZZ)Z", 1267 (void*) nativeSetBaseLayer }, 1268 { "nativeGetBaseLayer", "()I", 1269 (void*) nativeGetBaseLayer }, 1270 { "nativeReplaceBaseContent", "(I)V", 1271 (void*) nativeReplaceBaseContent }, 1272 { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V", 1273 (void*) nativeCopyBaseContentToPicture }, 1274 { "nativeHasContent", "()Z", 1275 (void*) nativeHasContent }, 1276 { "nativeDiscardAllTextures", "()V", 1277 (void*) nativeDiscardAllTextures }, 1278 { "nativeTileProfilingStart", "()V", 1279 (void*) nativeTileProfilingStart }, 1280 { "nativeTileProfilingStop", "()F", 1281 (void*) nativeTileProfilingStop }, 1282 { "nativeTileProfilingClear", "()V", 1283 (void*) nativeTileProfilingClear }, 1284 { "nativeTileProfilingNumFrames", "()I", 1285 (void*) nativeTileProfilingNumFrames }, 1286 { "nativeTileProfilingNumTilesInFrame", "(I)I", 1287 (void*) nativeTileProfilingNumTilesInFrame }, 1288 { "nativeTileProfilingGetInt", "(IILjava/lang/String;)I", 1289 (void*) nativeTileProfilingGetInt }, 1290 { "nativeTileProfilingGetFloat", "(IILjava/lang/String;)F", 1291 (void*) nativeTileProfilingGetFloat }, 1292 { "nativeStopGL", "()V", 1293 (void*) nativeStopGL }, 1294 { "nativeScrollableLayer", "(IILandroid/graphics/Rect;Landroid/graphics/Rect;)I", 1295 (void*) nativeScrollableLayer }, 1296 { "nativeScrollLayer", "(III)Z", 1297 (void*) nativeScrollLayer }, 1298 { "nativeSetIsScrolling", "(Z)V", 1299 (void*) nativeSetIsScrolling }, 1300 { "nativeUseHardwareAccelSkia", "(Z)V", 1301 (void*) nativeUseHardwareAccelSkia }, 1302 { "nativeGetBackgroundColor", "()I", 1303 (void*) nativeGetBackgroundColor }, 1304 { "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)Z", 1305 (void*) nativeSetProperty }, 1306 { "nativeGetProperty", "(Ljava/lang/String;)Ljava/lang/String;", 1307 (void*) nativeGetProperty }, 1308 { "nativeOnTrimMemory", "(I)V", 1309 (void*) nativeOnTrimMemory }, 1310 { "nativeSetPauseDrawing", "(IZ)V", 1311 (void*) nativeSetPauseDrawing }, 1312 { "nativeSetTextSelection", "(II)V", 1313 (void*) nativeSetTextSelection }, 1314 { "nativeGetHandleLayerId", "(IILandroid/graphics/Point;Landroid/webkit/QuadF;)I", 1315 (void*) nativeGetHandleLayerId }, 1316 { "nativeIsBaseFirst", "(I)Z", 1317 (void*) nativeIsBaseFirst }, 1318 { "nativeMapLayerRect", "(IILandroid/graphics/Rect;)V", 1319 (void*) nativeMapLayerRect }, 1320 { "nativeSetHwAccelerated", "(IZ)I", 1321 (void*) nativeSetHwAccelerated }, 1322}; 1323 1324int registerWebView(JNIEnv* env) 1325{ 1326 jclass clazz = env->FindClass("android/webkit/WebViewClassic"); 1327 ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebViewClassic"); 1328 gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I"); 1329 ALOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebViewClassic.mNativeClass"); 1330 env->DeleteLocalRef(clazz); 1331 1332 return jniRegisterNativeMethods(env, "android/webkit/WebViewClassic", gJavaWebViewMethods, NELEM(gJavaWebViewMethods)); 1333} 1334 1335} // namespace android 1336