WebView.cpp revision e859a34171f2a36877d95197d118d962078f8aa0
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 296void draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras) 297{ 298 if (!m_baseLayer) { 299 canvas->drawColor(bgColor); 300 return; 301 } 302 303 // draw the content of the base layer first 304 LayerContent* content = m_baseLayer->content(); 305 int sc = canvas->save(SkCanvas::kClip_SaveFlag); 306 int contentWidth = 0; 307 int contentHeight = 0; 308 if (content) { 309 contentWidth = content->width(); 310 contentHeight = content->height(); 311 } 312 canvas->clipRect(SkRect::MakeLTRB(0, 0, contentWidth, contentHeight), 313 SkRegion::kDifference_Op); 314 Color c = m_baseLayer->getBackgroundColor(); 315 canvas->drawColor(SkColorSetARGBInline(c.alpha(), c.red(), c.green(), c.blue())); 316 canvas->restoreToCount(sc); 317 318 // call this to be sure we've adjusted for any scrolling or animations 319 // before we actually draw 320 m_baseLayer->updateLayerPositions(m_visibleRect); 321 m_baseLayer->updatePositions(); 322 323 // We have to set the canvas' matrix on the base layer 324 // (to have fixed layers work as intended) 325 SkAutoCanvasRestore restore(canvas, true); 326 m_baseLayer->setMatrix(canvas->getTotalMatrix()); 327 canvas->resetMatrix(); 328 m_baseLayer->draw(canvas, getDrawExtra(extras)); 329} 330 331int getScaledMaxXScroll() 332{ 333 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 334 JNIEnv* env = JSC::Bindings::getJNIEnv(); 335 AutoJObject javaObject = m_javaGlue.object(env); 336 if (!javaObject.get()) 337 return 0; 338 int result = env->CallIntMethod(javaObject.get(), m_javaGlue.m_getScaledMaxXScroll); 339 checkException(env); 340 return result; 341} 342 343int getScaledMaxYScroll() 344{ 345 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 346 JNIEnv* env = JSC::Bindings::getJNIEnv(); 347 AutoJObject javaObject = m_javaGlue.object(env); 348 if (!javaObject.get()) 349 return 0; 350 int result = env->CallIntMethod(javaObject.get(), m_javaGlue.m_getScaledMaxYScroll); 351 checkException(env); 352 return result; 353} 354 355IntRect getVisibleRect() 356{ 357 IntRect rect; 358 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 359 JNIEnv* env = JSC::Bindings::getJNIEnv(); 360 AutoJObject javaObject = m_javaGlue.object(env); 361 if (!javaObject.get()) 362 return rect; 363 jobject jRect = env->CallObjectMethod(javaObject.get(), m_javaGlue.m_getVisibleRect); 364 checkException(env); 365 rect.setX(env->GetIntField(jRect, m_javaGlue.m_rectLeft)); 366 checkException(env); 367 rect.setY(env->GetIntField(jRect, m_javaGlue.m_rectTop)); 368 checkException(env); 369 rect.setWidth(env->CallIntMethod(jRect, m_javaGlue.m_rectWidth)); 370 checkException(env); 371 rect.setHeight(env->CallIntMethod(jRect, m_javaGlue.m_rectHeight)); 372 checkException(env); 373 env->DeleteLocalRef(jRect); 374 checkException(env); 375 return rect; 376} 377 378#if USE(ACCELERATED_COMPOSITING) 379static const ScrollableLayerAndroid* findScrollableLayer( 380 const LayerAndroid* parent, int x, int y, SkIRect* foundBounds) { 381 SkRect bounds; 382 parent->bounds(&bounds); 383 // Check the parent bounds first; this will clip to within a masking layer's 384 // bounds. 385 if (parent->masksToBounds() && !bounds.contains(x, y)) 386 return 0; 387 // Move the hit test local to parent. 388 x -= bounds.fLeft; 389 y -= bounds.fTop; 390 int count = parent->countChildren(); 391 while (count--) { 392 const LayerAndroid* child = parent->getChild(count); 393 const ScrollableLayerAndroid* result = findScrollableLayer(child, x, y, 394 foundBounds); 395 if (result) { 396 foundBounds->offset(bounds.fLeft, bounds.fTop); 397 if (parent->masksToBounds()) { 398 if (bounds.width() < foundBounds->width()) 399 foundBounds->fRight = foundBounds->fLeft + bounds.width(); 400 if (bounds.height() < foundBounds->height()) 401 foundBounds->fBottom = foundBounds->fTop + bounds.height(); 402 } 403 return result; 404 } 405 } 406 if (parent->contentIsScrollable()) { 407 foundBounds->set(0, 0, bounds.width(), bounds.height()); 408 return static_cast<const ScrollableLayerAndroid*>(parent); 409 } 410 return 0; 411} 412#endif 413 414int scrollableLayer(int x, int y, SkIRect* layerRect, SkIRect* bounds) 415{ 416#if USE(ACCELERATED_COMPOSITING) 417 if (!m_baseLayer) 418 return 0; 419 const ScrollableLayerAndroid* result = findScrollableLayer(m_baseLayer, x, y, bounds); 420 if (result) { 421 result->getScrollRect(layerRect); 422 return result->uniqueId(); 423 } 424#endif 425 return 0; 426} 427 428void scrollLayer(int layerId, int x, int y) 429{ 430 if (m_glWebViewState) 431 m_glWebViewState->scrollLayer(layerId, x, y); 432} 433 434void setHeightCanMeasure(bool measure) 435{ 436 m_heightCanMeasure = measure; 437} 438 439String getSelection() 440{ 441 SelectText* select = static_cast<SelectText*>( 442 getDrawExtra(WebView::DrawExtrasSelection)); 443 if (select) 444 return select->getText(); 445 return String(); 446} 447 448bool scrollBy(int dx, int dy) 449{ 450 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 451 452 JNIEnv* env = JSC::Bindings::getJNIEnv(); 453 AutoJObject javaObject = m_javaGlue.object(env); 454 if (!javaObject.get()) 455 return false; 456 bool result = env->CallBooleanMethod(javaObject.get(), m_javaGlue.m_scrollBy, dx, dy, true); 457 checkException(env); 458 return result; 459} 460 461void setIsScrolling(bool isScrolling) 462{ 463#if USE(ACCELERATED_COMPOSITING) 464 if (m_glWebViewState) 465 m_glWebViewState->setIsScrolling(isScrolling); 466#endif 467} 468 469void viewInvalidate() 470{ 471 JNIEnv* env = JSC::Bindings::getJNIEnv(); 472 AutoJObject javaObject = m_javaGlue.object(env); 473 if (!javaObject.get()) 474 return; 475 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_viewInvalidate); 476 checkException(env); 477} 478 479void viewInvalidateRect(int l, int t, int r, int b) 480{ 481 JNIEnv* env = JSC::Bindings::getJNIEnv(); 482 AutoJObject javaObject = m_javaGlue.object(env); 483 if (!javaObject.get()) 484 return; 485 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b); 486 checkException(env); 487} 488 489void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds) 490{ 491 JNIEnv* env = JSC::Bindings::getJNIEnv(); 492 AutoJObject javaObject = m_javaGlue.object(env); 493 if (!javaObject.get()) 494 return; 495 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_postInvalidateDelayed, 496 delay, bounds.x(), bounds.y(), bounds.maxX(), bounds.maxY()); 497 checkException(env); 498} 499 500#if ENABLE(ANDROID_OVERFLOW_SCROLL) 501static void copyScrollPositionRecursive(const LayerAndroid* from, 502 LayerAndroid* root) 503{ 504 if (!from || !root) 505 return; 506 for (int i = 0; i < from->countChildren(); i++) { 507 const LayerAndroid* l = from->getChild(i); 508 if (l->contentIsScrollable()) { 509 const SkPoint& pos = l->getPosition(); 510 LayerAndroid* match = root->findById(l->uniqueId()); 511 if (match && match->contentIsScrollable()) 512 match->setPosition(pos.fX, pos.fY); 513 } 514 copyScrollPositionRecursive(l, root); 515 } 516} 517#endif 518 519BaseLayerAndroid* getBaseLayer() const { return m_baseLayer; } 520 521bool setBaseLayer(BaseLayerAndroid* newBaseLayer, bool showVisualIndicator, 522 bool isPictureAfterFirstLayout) 523{ 524 bool queueFull = false; 525#if USE(ACCELERATED_COMPOSITING) 526 if (m_glWebViewState) 527 queueFull = m_glWebViewState->setBaseLayer(newBaseLayer, showVisualIndicator, 528 isPictureAfterFirstLayout); 529#endif 530 531#if ENABLE(ANDROID_OVERFLOW_SCROLL) 532 if (newBaseLayer) { 533 // TODO: the below tree position copies are only necessary in software rendering 534 copyScrollPositionRecursive(m_baseLayer, newBaseLayer); 535 } 536#endif 537 SkSafeUnref(m_baseLayer); 538 m_baseLayer = newBaseLayer; 539 540 return queueFull; 541} 542 543void copyBaseContentToPicture(SkPicture* picture) 544{ 545 if (!m_baseLayer) 546 return; 547 LayerContent* content = m_baseLayer->content(); 548 content->draw(picture->beginRecording(content->width(), content->height(), 549 SkPicture::kUsePathBoundsForClip_RecordingFlag)); 550 picture->endRecording(); 551} 552 553bool hasContent() { 554 if (!m_baseLayer) 555 return false; 556 return !m_baseLayer->content()->isEmpty(); 557} 558 559void setFunctor(Functor* functor) { 560 delete m_glDrawFunctor; 561 m_glDrawFunctor = functor; 562} 563 564Functor* getFunctor() { 565 return m_glDrawFunctor; 566} 567 568void setVisibleRect(SkRect& visibleRect) { 569 m_visibleRect = visibleRect; 570} 571 572void setDrawExtra(DrawExtra *extra, DrawExtras type) 573{ 574 if (type == DrawExtrasNone) 575 return; 576 DrawExtra* old = m_extras[type - 1]; 577 m_extras[type - 1] = extra; 578 if (old != extra) { 579 delete old; 580 } 581} 582 583void setTextSelection(SelectText *selection) { 584 setDrawExtra(selection, DrawExtrasSelection); 585} 586 587const TransformationMatrix* getLayerTransform(int layerId) { 588 if (layerId != -1 && m_baseLayer) { 589 LayerAndroid* layer = m_baseLayer->findById(layerId); 590 // We need to make sure the drawTransform is up to date as this is 591 // called before a draw() or drawGL() 592 if (layer) { 593 m_baseLayer->updateLayerPositions(m_visibleRect); 594 return layer->drawTransform(); 595 } 596 } 597 return 0; 598} 599 600int getHandleLayerId(SelectText::HandleId handleId, SkIPoint& cursorPoint, 601 FloatQuad& textBounds) { 602 SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection)); 603 if (!selectText || !m_baseLayer) 604 return -1; 605 int layerId = selectText->caretLayerId(handleId); 606 IntRect cursorRect = selectText->caretRect(handleId); 607 IntRect textRect = selectText->textRect(handleId); 608 // Rects exclude the last pixel on right/bottom. We want only included pixels. 609 cursorPoint.set(cursorRect.x(), cursorRect.maxY() - 1); 610 textRect.setHeight(std::max(1, textRect.height() - 1)); 611 textRect.setWidth(std::max(1, textRect.width() - 1)); 612 textBounds = FloatQuad(textRect); 613 614 const TransformationMatrix* transform = getLayerTransform(layerId); 615 if (transform) { 616 // We're overloading the concept of Rect to be just the two 617 // points (bottom-left and top-right. 618 cursorPoint = transform->mapPoint(cursorPoint); 619 textBounds = transform->mapQuad(textBounds); 620 } 621 return layerId; 622} 623 624void mapLayerRect(int layerId, SkIRect& rect) { 625 const TransformationMatrix* transform = getLayerTransform(layerId); 626 if (transform) 627 transform->mapRect(rect); 628} 629 630void floatQuadToQuadF(JNIEnv* env, const FloatQuad& nativeTextQuad, 631 jobject textQuad) 632{ 633 jobject p1 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP1); 634 jobject p2 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP2); 635 jobject p3 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP3); 636 jobject p4 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP4); 637 GraphicsJNI::point_to_jpointf(nativeTextQuad.p1(), env, p1); 638 GraphicsJNI::point_to_jpointf(nativeTextQuad.p2(), env, p2); 639 GraphicsJNI::point_to_jpointf(nativeTextQuad.p3(), env, p3); 640 GraphicsJNI::point_to_jpointf(nativeTextQuad.p4(), env, p4); 641 env->DeleteLocalRef(p1); 642 env->DeleteLocalRef(p2); 643 env->DeleteLocalRef(p3); 644 env->DeleteLocalRef(p4); 645} 646 647// This is called when WebView switches rendering modes in a more permanent fashion 648// such as when the layer type is set or the view is attached/detached from the window 649int setHwAccelerated(bool hwAccelerated) { 650 if (!m_glWebViewState) 651 return 0; 652 LayerAndroid* root = m_baseLayer; 653 if (root) 654 return root->setHwAccelerated(hwAccelerated); 655 return 0; 656} 657 658 bool m_isDrawingPaused; 659private: // local state for WebView 660 // private to getFrameCache(); other functions operate in a different thread 661 WebViewCore* m_viewImpl; 662 int m_generation; // associate unique ID with sent kit focus to match with ui 663 // Corresponds to the same-named boolean on the java side. 664 bool m_heightCanMeasure; 665 int m_lastDx; 666 SkMSec m_lastDxTime; 667 DrawExtra* m_extras[DRAW_EXTRAS_SIZE]; 668 BaseLayerAndroid* m_baseLayer; 669 Functor* m_glDrawFunctor; 670#if USE(ACCELERATED_COMPOSITING) 671 GLWebViewState* m_glWebViewState; 672#endif 673 SkRect m_visibleRect; 674 bool m_isHighEndGfx; 675}; // end of WebView class 676 677 678/** 679 * This class holds a function pointer and parameters for calling drawGL into a specific 680 * viewport. The pointer to the Functor will be put on a framework display list to be called 681 * when the display list is replayed. 682 */ 683class GLDrawFunctor : Functor { 684 public: 685 GLDrawFunctor(WebView* _wvInstance, 686 int (WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*, 687 WebCore::IntRect&, int, WebCore::IntRect&, jfloat, jint, bool), 688 WebCore::IntRect _viewRect, float _scale, int _extras) { 689 wvInstance = _wvInstance; 690 funcPtr = _funcPtr; 691 viewRect = _viewRect; 692 scale = _scale; 693 extras = _extras; 694 }; 695 696 status_t operator()(int messageId, void* data) { 697 TRACE_METHOD(); 698 699 if (viewRect.isEmpty()) { 700 // NOOP operation if viewport is empty 701 return 0; 702 } 703 704 WebCore::IntRect inval; 705 int titlebarHeight = webViewRect.height() - viewRect.height(); 706 707 uirenderer::DrawGlInfo* info = reinterpret_cast<uirenderer::DrawGlInfo*>(data); 708 WebCore::IntRect clip(info->clipLeft, info->clipTop, 709 info->clipRight - info->clipLeft, 710 info->clipBottom - info->clipTop); 711 712 WebCore::IntRect localViewRect = viewRect; 713 if (info->isLayer) { 714 // When webview is on a layer, we need to use the viewport relative 715 // to the FBO, rather than the screen(which will use viewRect). 716 localViewRect.setX(clip.x()); 717 localViewRect.setY(info->height - clip.y() - clip.height()); 718 } 719 bool shouldDraw = (messageId == uirenderer::DrawGlInfo::kModeDraw); 720 // Send the necessary info to the shader. 721 TilesManager::instance()->shader()->setGLDrawInfo(info); 722 723 int returnFlags = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect, 724 titlebarHeight, clip, scale, extras, shouldDraw); 725 if ((returnFlags & uirenderer::DrawGlInfo::kStatusDraw) != 0) { 726 IntRect finalInval; 727 if (inval.isEmpty()) 728 finalInval = webViewRect; 729 else { 730 finalInval.setX(webViewRect.x() + inval.x()); 731 finalInval.setY(webViewRect.y() + titlebarHeight + inval.y()); 732 finalInval.setWidth(inval.width()); 733 finalInval.setHeight(inval.height()); 734 } 735 info->dirtyLeft = finalInval.x(); 736 info->dirtyTop = finalInval.y(); 737 info->dirtyRight = finalInval.maxX(); 738 info->dirtyBottom = finalInval.maxY(); 739 } 740 // return 1 if invalidation needed, 2 to request non-drawing functor callback, 0 otherwise 741 ALOGV("returnFlags are %d, shouldDraw %d", returnFlags, shouldDraw); 742 return returnFlags; 743 } 744 void updateRect(WebCore::IntRect& _viewRect) { 745 viewRect = _viewRect; 746 } 747 void updateViewRect(WebCore::IntRect& _viewRect) { 748 webViewRect = _viewRect; 749 } 750 void updateScale(float _scale) { 751 scale = _scale; 752 } 753 void updateExtras(jint _extras) { 754 extras = _extras; 755 } 756 private: 757 WebView* wvInstance; 758 int (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*, 759 WebCore::IntRect&, int, WebCore::IntRect&, float, int, bool); 760 WebCore::IntRect viewRect; 761 WebCore::IntRect webViewRect; 762 jfloat scale; 763 jint extras; 764}; 765 766/* 767 * Native JNI methods 768 */ 769 770static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl, 771 jstring drawableDir, jboolean isHighEndGfx) 772{ 773 WTF::String dir = jstringToWtfString(env, drawableDir); 774 new WebView(env, obj, viewImpl, dir, isHighEndGfx); 775 // NEED THIS OR SOMETHING LIKE IT! 776 //Release(obj); 777} 778 779static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj) 780{ 781 if (obj) { 782 int L, T, R, B; 783 GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B); 784 return WebCore::IntRect(L, T, R - L, B - T); 785 } else 786 return WebCore::IntRect(); 787} 788 789static SkRect jrectf_to_rect(JNIEnv* env, jobject obj) 790{ 791 SkRect rect = SkRect::MakeEmpty(); 792 if (obj) 793 GraphicsJNI::jrectf_to_rect(env, obj, &rect); 794 return rect; 795} 796 797static void nativeDraw(JNIEnv *env, jobject obj, jobject canv, 798 jobject visible, jint color, 799 jint extras) { 800 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); 801 WebView* webView = GET_NATIVE_VIEW(env, obj); 802 SkRect visibleRect = jrectf_to_rect(env, visible); 803 webView->setVisibleRect(visibleRect); 804 webView->draw(canvas, color, static_cast<WebView::DrawExtras>(extras)); 805} 806 807static jint nativeCreateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView, 808 jobject jrect, jobject jviewrect, 809 jobject jvisiblerect, 810 jfloat scale, jint extras) { 811 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); 812 WebView *wvInstance = (WebView*) nativeView; 813 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect); 814 wvInstance->setVisibleRect(visibleRect); 815 816 GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor(); 817 if (!functor) { 818 functor = new GLDrawFunctor(wvInstance, &android::WebView::drawGL, 819 viewRect, scale, extras); 820 wvInstance->setFunctor((Functor*) functor); 821 } else { 822 functor->updateRect(viewRect); 823 functor->updateScale(scale); 824 functor->updateExtras(extras); 825 } 826 827 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect); 828 functor->updateViewRect(webViewRect); 829 830 return (jint)functor; 831} 832 833static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView) { 834 WebView *wvInstance = (WebView*) nativeView; 835 if (!wvInstance) 836 return 0; 837 838 return (jint) wvInstance->getFunctor(); 839} 840 841static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView, jobject jrect, 842 jobject jviewrect, jobject jvisiblerect, jfloat scale) { 843 WebView *wvInstance = (WebView*) nativeView; 844 if (wvInstance) { 845 GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor(); 846 if (functor) { 847 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); 848 functor->updateRect(viewRect); 849 850 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect); 851 wvInstance->setVisibleRect(visibleRect); 852 853 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect); 854 functor->updateViewRect(webViewRect); 855 856 functor->updateScale(scale); 857 } 858 } 859} 860 861static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint nativeView) 862{ 863 // only call in software rendering, initialize and evaluate animations 864#if USE(ACCELERATED_COMPOSITING) 865 BaseLayerAndroid* baseLayer = ((WebView*)nativeView)->getBaseLayer(); 866 if (baseLayer) { 867 baseLayer->initAnimations(); 868 return baseLayer->evaluateAnimations(); 869 } 870#endif 871 return false; 872} 873 874static bool nativeSetBaseLayer(JNIEnv *env, jobject obj, jint nativeView, jint layer, 875 jboolean showVisualIndicator, 876 jboolean isPictureAfterFirstLayout) 877{ 878 BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer); 879 return ((WebView*)nativeView)->setBaseLayer(layerImpl, showVisualIndicator, 880 isPictureAfterFirstLayout); 881} 882 883static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj) 884{ 885 return GET_NATIVE_VIEW(env, obj)->getBaseLayer(); 886} 887 888static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pict) 889{ 890 SkPicture* picture = GraphicsJNI::getNativePicture(env, pict); 891 GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture); 892} 893 894static bool nativeHasContent(JNIEnv *env, jobject obj) 895{ 896 return GET_NATIVE_VIEW(env, obj)->hasContent(); 897} 898 899static jobject nativeLayerBounds(JNIEnv* env, jobject obj, jint jlayer) 900{ 901 SkRect r; 902#if USE(ACCELERATED_COMPOSITING) 903 LayerAndroid* layer = (LayerAndroid*) jlayer; 904 r = layer->bounds(); 905#else 906 r.setEmpty(); 907#endif 908 SkIRect irect; 909 r.round(&irect); 910 jclass rectClass = env->FindClass("android/graphics/Rect"); 911 jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V"); 912 jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop, 913 irect.fRight, irect.fBottom); 914 env->DeleteLocalRef(rectClass); 915 return rect; 916} 917 918static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure) 919{ 920 WebView* view = GET_NATIVE_VIEW(env, obj); 921 ALOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure"); 922 view->setHeightCanMeasure(measure); 923} 924 925static void nativeDestroy(JNIEnv *env, jobject obj) 926{ 927 WebView* view = GET_NATIVE_VIEW(env, obj); 928 ALOGD("nativeDestroy view: %p", view); 929 ALOG_ASSERT(view, "view not set in nativeDestroy"); 930 delete view; 931} 932 933static void nativeStopGL(JNIEnv *env, jobject obj) 934{ 935 GET_NATIVE_VIEW(env, obj)->stopGL(); 936} 937 938static jobject nativeGetSelection(JNIEnv *env, jobject obj) 939{ 940 WebView* view = GET_NATIVE_VIEW(env, obj); 941 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 942 String selection = view->getSelection(); 943 return wtfStringToJstring(env, selection); 944} 945 946static void nativeDiscardAllTextures(JNIEnv *env, jobject obj) 947{ 948 //discard all textures for debugging/test purposes, but not gl backing memory 949 bool allTextures = true, deleteGLTextures = false; 950 TilesManager::instance()->discardTextures(allTextures, deleteGLTextures); 951} 952 953static void nativeTileProfilingStart(JNIEnv *env, jobject obj) 954{ 955 TilesManager::instance()->getProfiler()->start(); 956} 957 958static float nativeTileProfilingStop(JNIEnv *env, jobject obj) 959{ 960 return TilesManager::instance()->getProfiler()->stop(); 961} 962 963static void nativeTileProfilingClear(JNIEnv *env, jobject obj) 964{ 965 TilesManager::instance()->getProfiler()->clear(); 966} 967 968static int nativeTileProfilingNumFrames(JNIEnv *env, jobject obj) 969{ 970 return TilesManager::instance()->getProfiler()->numFrames(); 971} 972 973static int nativeTileProfilingNumTilesInFrame(JNIEnv *env, jobject obj, int frame) 974{ 975 return TilesManager::instance()->getProfiler()->numTilesInFrame(frame); 976} 977 978static int nativeTileProfilingGetInt(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey) 979{ 980 WTF::String key = jstringToWtfString(env, jkey); 981 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile); 982 983 if (key == "left") 984 return record->left; 985 if (key == "top") 986 return record->top; 987 if (key == "right") 988 return record->right; 989 if (key == "bottom") 990 return record->bottom; 991 if (key == "level") 992 return record->level; 993 if (key == "isReady") 994 return record->isReady ? 1 : 0; 995 return -1; 996} 997 998static float nativeTileProfilingGetFloat(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey) 999{ 1000 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile); 1001 return record->scale; 1002} 1003 1004#ifdef ANDROID_DUMP_DISPLAY_TREE 1005static void dumpToFile(const char text[], void* file) { 1006 fwrite(text, 1, strlen(text), reinterpret_cast<FILE*>(file)); 1007 fwrite("\n", 1, 1, reinterpret_cast<FILE*>(file)); 1008} 1009#endif 1010 1011// Return true to view invalidate WebView 1012static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jvalue) 1013{ 1014 WTF::String key = jstringToWtfString(env, jkey); 1015 WTF::String value = jstringToWtfString(env, jvalue); 1016 if (key == "inverted") { 1017 bool shouldInvert = (value == "true"); 1018 TilesManager::instance()->setInvertedScreen(shouldInvert); 1019 return true; 1020 } 1021 else if (key == "inverted_contrast") { 1022 float contrast = value.toFloat(); 1023 TilesManager::instance()->setInvertedScreenContrast(contrast); 1024 return true; 1025 } 1026 else if (key == "enable_cpu_upload_path") { 1027 TilesManager::instance()->transferQueue()->setTextureUploadType( 1028 value == "true" ? CpuUpload : GpuUpload); 1029 } 1030 else if (key == "use_minimal_memory") { 1031 TilesManager::instance()->setUseMinimalMemory(value == "true"); 1032 } 1033 else if (key == "use_double_buffering") { 1034 TilesManager::instance()->setUseDoubleBuffering(value == "true"); 1035 } 1036 else if (key == "tree_updates") { 1037 TilesManager::instance()->clearContentUpdates(); 1038 } 1039 return false; 1040} 1041 1042static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring jkey) 1043{ 1044 WTF::String key = jstringToWtfString(env, jkey); 1045 if (key == "tree_updates") { 1046 int updates = TilesManager::instance()->getContentUpdates(); 1047 WTF::String wtfUpdates = WTF::String::number(updates); 1048 return wtfStringToJstring(env, wtfUpdates); 1049 } 1050 return 0; 1051} 1052 1053static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level) 1054{ 1055 if (TilesManager::hardwareAccelerationEnabled()) { 1056 // When we got TRIM_MEMORY_MODERATE or TRIM_MEMORY_COMPLETE, we should 1057 // make sure the transfer queue is empty and then abandon the Surface 1058 // Texture to avoid ANR b/c framework may destroy the EGL context. 1059 // Refer to WindowManagerImpl.java for conditions we followed. 1060 TilesManager* tilesManager = TilesManager::instance(); 1061 if ((level >= TRIM_MEMORY_MODERATE 1062 && !tilesManager->highEndGfx()) 1063 || level >= TRIM_MEMORY_COMPLETE) { 1064 ALOGD("OnTrimMemory with EGL Context %p", eglGetCurrentContext()); 1065 tilesManager->cleanupGLResources(); 1066 } 1067 1068 bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true; 1069 tilesManager->discardTextures(freeAllTextures, glTextures); 1070 } 1071} 1072 1073static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl) 1074{ 1075#ifdef ANDROID_DUMP_DISPLAY_TREE 1076 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1077 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1078 1079 if (view && view->getWebViewCore()) { 1080 FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w"); 1081 if (file) { 1082 SkFormatDumper dumper(dumpToFile, file); 1083 // dump the URL 1084 if (jurl) { 1085 const char* str = env->GetStringUTFChars(jurl, 0); 1086 SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE); 1087 dumpToFile(str, file); 1088 env->ReleaseStringUTFChars(jurl, str); 1089 } 1090 // now dump the display tree 1091 SkDumpCanvas canvas(&dumper); 1092 // this will playback the picture into the canvas, which will 1093 // spew its contents to the dumper 1094 view->draw(&canvas, 0, WebView::DrawExtrasNone); 1095 // we're done with the file now 1096 fwrite("\n", 1, 1, file); 1097 fclose(file); 1098 } 1099#if USE(ACCELERATED_COMPOSITING) 1100 const LayerAndroid* baseLayer = view->getBaseLayer(); 1101 if (baseLayer) { 1102 FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w"); 1103 if (file) { 1104 baseLayer->dumpLayers(file, 0); 1105 fclose(file); 1106 } 1107 } 1108#endif 1109 } 1110#endif 1111} 1112 1113static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint nativeView, 1114 jint x, jint y, jobject rect, jobject bounds) 1115{ 1116 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1117 ALOG_ASSERT(webview, "webview not set in %s", __FUNCTION__); 1118 SkIRect nativeRect, nativeBounds; 1119 int id = webview->scrollableLayer(x, y, &nativeRect, &nativeBounds); 1120 if (rect) 1121 GraphicsJNI::irect_to_jrect(nativeRect, env, rect); 1122 if (bounds) 1123 GraphicsJNI::irect_to_jrect(nativeBounds, env, bounds); 1124 return id; 1125} 1126 1127static bool nativeScrollLayer(JNIEnv* env, jobject obj, 1128 jint nativeView, jint layerId, jint x, jint y) 1129{ 1130#if ENABLE(ANDROID_OVERFLOW_SCROLL) 1131 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1132 webview->scrollLayer(layerId, x, y); 1133 1134 //TODO: the below only needed for the SW rendering path 1135 LayerAndroid* baseLayer = webview->getBaseLayer(); 1136 if (!baseLayer) 1137 return false; 1138 LayerAndroid* layer = baseLayer->findById(layerId); 1139 if (!layer || !layer->contentIsScrollable()) 1140 return false; 1141 return static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); 1142#endif 1143 return false; 1144} 1145 1146static void nativeSetIsScrolling(JNIEnv* env, jobject jwebview, jboolean isScrolling) 1147{ 1148 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1149 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1150 view->setIsScrolling(isScrolling); 1151} 1152 1153static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled) 1154{ 1155 BaseRenderer::setCurrentRendererType(enabled ? BaseRenderer::Ganesh : BaseRenderer::Raster); 1156} 1157 1158static int nativeGetBackgroundColor(JNIEnv* env, jobject obj) 1159{ 1160 WebView* view = GET_NATIVE_VIEW(env, obj); 1161 BaseLayerAndroid* baseLayer = view->getBaseLayer(); 1162 if (baseLayer) { 1163 WebCore::Color color = baseLayer->getBackgroundColor(); 1164 if (color.isValid()) 1165 return SkColorSetARGB(color.alpha(), color.red(), 1166 color.green(), color.blue()); 1167 } 1168 return SK_ColorWHITE; 1169} 1170 1171static void nativeSetPauseDrawing(JNIEnv *env, jobject obj, jint nativeView, 1172 jboolean pause) 1173{ 1174 ((WebView*)nativeView)->m_isDrawingPaused = pause; 1175} 1176 1177static void nativeSetTextSelection(JNIEnv *env, jobject obj, jint nativeView, 1178 jint selectionPtr) 1179{ 1180 SelectText* selection = reinterpret_cast<SelectText*>(selectionPtr); 1181 reinterpret_cast<WebView*>(nativeView)->setTextSelection(selection); 1182} 1183 1184static jint nativeGetHandleLayerId(JNIEnv *env, jobject obj, jint nativeView, 1185 jint handleIndex, jobject cursorPoint, 1186 jobject textQuad) 1187{ 1188 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1189 SkIPoint nativePoint; 1190 FloatQuad nativeTextQuad; 1191 int layerId = webview->getHandleLayerId((SelectText::HandleId) handleIndex, 1192 nativePoint, nativeTextQuad); 1193 if (cursorPoint) 1194 GraphicsJNI::ipoint_to_jpoint(nativePoint, env, cursorPoint); 1195 if (textQuad) 1196 webview->floatQuadToQuadF(env, nativeTextQuad, textQuad); 1197 return layerId; 1198} 1199 1200static jboolean nativeIsBaseFirst(JNIEnv *env, jobject obj, jint nativeView) 1201{ 1202 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1203 SelectText* select = static_cast<SelectText*>( 1204 webview->getDrawExtra(WebView::DrawExtrasSelection)); 1205 return select ? select->isBaseFirst() : false; 1206} 1207 1208static void nativeMapLayerRect(JNIEnv *env, jobject obj, jint nativeView, 1209 jint layerId, jobject rect) 1210{ 1211 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1212 SkIRect nativeRect; 1213 GraphicsJNI::jrect_to_irect(env, rect, &nativeRect); 1214 webview->mapLayerRect(layerId, nativeRect); 1215 GraphicsJNI::irect_to_jrect(nativeRect, env, rect); 1216} 1217 1218static jint nativeSetHwAccelerated(JNIEnv *env, jobject obj, jint nativeView, 1219 jboolean hwAccelerated) 1220{ 1221 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1222 return webview->setHwAccelerated(hwAccelerated); 1223} 1224 1225/* 1226 * JNI registration 1227 */ 1228static JNINativeMethod gJavaWebViewMethods[] = { 1229 { "nativeCreate", "(ILjava/lang/String;Z)V", 1230 (void*) nativeCreate }, 1231 { "nativeDestroy", "()V", 1232 (void*) nativeDestroy }, 1233 { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;II)V", 1234 (void*) nativeDraw }, 1235 { "nativeCreateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I", 1236 (void*) nativeCreateDrawGLFunction }, 1237 { "nativeGetDrawGLFunction", "(I)I", 1238 (void*) nativeGetDrawGLFunction }, 1239 { "nativeUpdateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;F)V", 1240 (void*) nativeUpdateDrawGLFunction }, 1241 { "nativeDumpDisplayTree", "(Ljava/lang/String;)V", 1242 (void*) nativeDumpDisplayTree }, 1243 { "nativeEvaluateLayersAnimations", "(I)Z", 1244 (void*) nativeEvaluateLayersAnimations }, 1245 { "nativeGetSelection", "()Ljava/lang/String;", 1246 (void*) nativeGetSelection }, 1247 { "nativeLayerBounds", "(I)Landroid/graphics/Rect;", 1248 (void*) nativeLayerBounds }, 1249 { "nativeSetHeightCanMeasure", "(Z)V", 1250 (void*) nativeSetHeightCanMeasure }, 1251 { "nativeSetBaseLayer", "(IIZZ)Z", 1252 (void*) nativeSetBaseLayer }, 1253 { "nativeGetBaseLayer", "()I", 1254 (void*) nativeGetBaseLayer }, 1255 { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V", 1256 (void*) nativeCopyBaseContentToPicture }, 1257 { "nativeHasContent", "()Z", 1258 (void*) nativeHasContent }, 1259 { "nativeDiscardAllTextures", "()V", 1260 (void*) nativeDiscardAllTextures }, 1261 { "nativeTileProfilingStart", "()V", 1262 (void*) nativeTileProfilingStart }, 1263 { "nativeTileProfilingStop", "()F", 1264 (void*) nativeTileProfilingStop }, 1265 { "nativeTileProfilingClear", "()V", 1266 (void*) nativeTileProfilingClear }, 1267 { "nativeTileProfilingNumFrames", "()I", 1268 (void*) nativeTileProfilingNumFrames }, 1269 { "nativeTileProfilingNumTilesInFrame", "(I)I", 1270 (void*) nativeTileProfilingNumTilesInFrame }, 1271 { "nativeTileProfilingGetInt", "(IILjava/lang/String;)I", 1272 (void*) nativeTileProfilingGetInt }, 1273 { "nativeTileProfilingGetFloat", "(IILjava/lang/String;)F", 1274 (void*) nativeTileProfilingGetFloat }, 1275 { "nativeStopGL", "()V", 1276 (void*) nativeStopGL }, 1277 { "nativeScrollableLayer", "(IIILandroid/graphics/Rect;Landroid/graphics/Rect;)I", 1278 (void*) nativeScrollableLayer }, 1279 { "nativeScrollLayer", "(IIII)Z", 1280 (void*) nativeScrollLayer }, 1281 { "nativeSetIsScrolling", "(Z)V", 1282 (void*) nativeSetIsScrolling }, 1283 { "nativeUseHardwareAccelSkia", "(Z)V", 1284 (void*) nativeUseHardwareAccelSkia }, 1285 { "nativeGetBackgroundColor", "()I", 1286 (void*) nativeGetBackgroundColor }, 1287 { "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)Z", 1288 (void*) nativeSetProperty }, 1289 { "nativeGetProperty", "(Ljava/lang/String;)Ljava/lang/String;", 1290 (void*) nativeGetProperty }, 1291 { "nativeOnTrimMemory", "(I)V", 1292 (void*) nativeOnTrimMemory }, 1293 { "nativeSetPauseDrawing", "(IZ)V", 1294 (void*) nativeSetPauseDrawing }, 1295 { "nativeSetTextSelection", "(II)V", 1296 (void*) nativeSetTextSelection }, 1297 { "nativeGetHandleLayerId", "(IILandroid/graphics/Point;Landroid/webkit/QuadF;)I", 1298 (void*) nativeGetHandleLayerId }, 1299 { "nativeIsBaseFirst", "(I)Z", 1300 (void*) nativeIsBaseFirst }, 1301 { "nativeMapLayerRect", "(IILandroid/graphics/Rect;)V", 1302 (void*) nativeMapLayerRect }, 1303 { "nativeSetHwAccelerated", "(IZ)I", 1304 (void*) nativeSetHwAccelerated }, 1305}; 1306 1307int registerWebView(JNIEnv* env) 1308{ 1309 jclass clazz = env->FindClass("android/webkit/WebViewClassic"); 1310 ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebViewClassic"); 1311 gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I"); 1312 ALOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebViewClassic.mNativeClass"); 1313 env->DeleteLocalRef(clazz); 1314 1315 return jniRegisterNativeMethods(env, "android/webkit/WebViewClassic", gJavaWebViewMethods, NELEM(gJavaWebViewMethods)); 1316} 1317 1318} // namespace android 1319