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