diff options
-rw-r--r-- | Source/Android.mk | 312 | ||||
-rw-r--r-- | Source/WebCore/css/mediaControlsAndroid.css | 5 | ||||
-rw-r--r-- | Source/WebCore/editing/SelectionController.cpp | 7 | ||||
-rw-r--r-- | Source/WebCore/html/HTMLMediaElement.cpp | 2 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/BaseRenderer.cpp | 20 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/BaseTile.cpp | 89 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/BaseTileTexture.h | 1 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/GLUtils.cpp | 38 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/GLUtils.h | 4 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/RasterRenderer.cpp | 10 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/TransferQueue.cpp | 73 | ||||
-rw-r--r-- | Source/WebCore/platform/graphics/android/TransferQueue.h | 5 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.cpp | 193 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.h | 17 | ||||
-rw-r--r-- | Source/WebKit/android/nav/DrawExtra.cpp | 5 | ||||
-rw-r--r-- | Source/WebKit/android/nav/DrawExtra.h | 3 | ||||
-rw-r--r-- | Source/WebKit/android/nav/WebView.cpp | 11 |
17 files changed, 292 insertions, 503 deletions
diff --git a/Source/Android.mk b/Source/Android.mk deleted file mode 100644 index 6612cae..0000000 --- a/Source/Android.mk +++ /dev/null @@ -1,312 +0,0 @@ -## -## Copyright 2009, The Android Open Source Project -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## * Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## * Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. -## -## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -## - -LOCAL_PATH := $(call my-dir) - -# Two ways to control which JS engine is used: -# 1. use JS_ENGINE environment variable, value can be either 'jsc' or 'v8' -# This is the preferred way. -# 2. if JS_ENGINE is not set, or is not 'jsc' or 'v8', this makefile picks -# up a default engine to build. -# To help setup buildbot, a new environment variable, USE_ALT_JS_ENGINE, -# can be set to true, so that two builds can be different but without -# specifying which JS engine to use. -# To enable JIT in Android's JSC, please set ENABLE_JSC_JIT environment -# variable to true. - -# Read JS_ENGINE environment variable -JAVASCRIPT_ENGINE = $(JS_ENGINE) - -ifneq ($(JAVASCRIPT_ENGINE),jsc) - ifneq ($(JAVASCRIPT_ENGINE),v8) - # No JS engine is specified, pickup the one we want as default. - ifeq ($(USE_ALT_JS_ENGINE),true) - JAVASCRIPT_ENGINE = v8 - else - JAVASCRIPT_ENGINE = jsc - endif - endif -endif - -BASE_PATH := $(call my-dir) -include $(CLEAR_VARS) - -# Define our module and find the intermediates directory -LOCAL_MODULE := libwebcore -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -base_intermediates := $(call local-intermediates-dir) - -# Using := here prevents recursive expansion -WEBKIT_SRC_FILES := - -# We have to use bison 2.3 -include $(BASE_PATH)/bison_check.mk - -# Build our list of include paths. We include WebKit/android/icu first so that -# any files that include <unicode/ucnv.h> will include our ucnv.h first. We -# also add external/ as an include directory so that we can specify the real -# icu header directory as a more exact reference to avoid including our ucnv.h. -# -# Note that JavasCriptCore/ must be included after WebCore/, so that we pick up -# the right config.h. -LOCAL_C_INCLUDES := \ - $(JNI_H_INCLUDE) \ - $(LOCAL_PATH)/WebKit/android/icu \ - external/ \ - external/icu4c/common \ - external/icu4c/i18n \ - external/libxml2/include \ - external/skia/emoji \ - external/skia/include/core \ - external/skia/include/effects \ - external/skia/include/images \ - external/skia/include/ports \ - external/skia/include/utils \ - external/skia/src/ports \ - external/sqlite/dist \ - frameworks/base/core/jni/android/graphics - -LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ - $(LOCAL_PATH)/WebCore \ - $(LOCAL_PATH)/WebCore/accessibility \ - $(LOCAL_PATH)/WebCore/bindings/generic \ - $(LOCAL_PATH)/WebCore/css \ - $(LOCAL_PATH)/WebCore/dom \ - $(LOCAL_PATH)/WebCore/editing \ - $(LOCAL_PATH)/WebCore/history \ - $(LOCAL_PATH)/WebCore/history/android \ - $(LOCAL_PATH)/WebCore/html \ - $(LOCAL_PATH)/WebCore/html/canvas \ - $(LOCAL_PATH)/WebCore/inspector \ - $(LOCAL_PATH)/WebCore/loader \ - $(LOCAL_PATH)/WebCore/loader/appcache \ - $(LOCAL_PATH)/WebCore/loader/icon \ - $(LOCAL_PATH)/WebCore/notifications \ - $(LOCAL_PATH)/WebCore/page \ - $(LOCAL_PATH)/WebCore/page/android \ - $(LOCAL_PATH)/WebCore/page/animation \ - $(LOCAL_PATH)/WebCore/platform \ - $(LOCAL_PATH)/WebCore/platform/android \ - $(LOCAL_PATH)/WebCore/platform/animation \ - $(LOCAL_PATH)/WebCore/platform/graphics \ - $(LOCAL_PATH)/WebCore/platform/graphics/android \ - $(LOCAL_PATH)/WebCore/platform/graphics/network \ - $(LOCAL_PATH)/WebCore/platform/graphics/skia \ - $(LOCAL_PATH)/WebCore/platform/graphics/transforms \ - $(LOCAL_PATH)/WebCore/platform/image-decoders \ - $(LOCAL_PATH)/WebCore/platform/leveldb \ - $(LOCAL_PATH)/WebCore/platform/mock \ - $(LOCAL_PATH)/WebCore/platform/network \ - $(LOCAL_PATH)/WebCore/platform/network/android \ - $(LOCAL_PATH)/WebCore/platform/sql \ - $(LOCAL_PATH)/WebCore/platform/text \ - $(LOCAL_PATH)/WebCore/plugins \ - $(LOCAL_PATH)/WebCore/plugins/android \ - $(LOCAL_PATH)/WebCore/rendering \ - $(LOCAL_PATH)/WebCore/rendering/style \ - $(LOCAL_PATH)/WebCore/storage \ - $(LOCAL_PATH)/WebCore/workers \ - $(LOCAL_PATH)/WebCore/xml - -LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ - $(LOCAL_PATH)/WebKit/android \ - $(LOCAL_PATH)/WebKit/android/WebCoreSupport \ - $(LOCAL_PATH)/WebKit/android/jni \ - $(LOCAL_PATH)/WebKit/android/nav \ - $(LOCAL_PATH)/WebKit/android/plugins \ - $(LOCAL_PATH)/WebKit/android/stl - -LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ - $(LOCAL_PATH)/JavaScriptCore \ - $(LOCAL_PATH)/JavaScriptCore/wtf \ - $(LOCAL_PATH)/JavaScriptCore/wtf/unicode \ - $(LOCAL_PATH)/JavaScriptCore/wtf/unicode/icu - -LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ - $(base_intermediates)/WebCore/ \ - $(base_intermediates)/WebCore/css \ - $(base_intermediates)/WebCore/html \ - $(base_intermediates)/WebCore/platform - -ifeq ($(ENABLE_SVG), true) -LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ - $(LOCAL_PATH)/WebCore/platform/graphics/filters \ - $(LOCAL_PATH)/WebCore/svg \ - $(LOCAL_PATH)/WebCore/svg/animation \ - $(LOCAL_PATH)/WebCore/svg/graphics \ - $(LOCAL_PATH)/WebCore/svg/graphics/filters \ - $(base_intermediates)/WebCore/svg -endif - -ifeq ($(JAVASCRIPT_ENGINE),v8) -# Include WTF source file. -d := JavaScriptCore -LOCAL_PATH := $(BASE_PATH)/$d -intermediates := $(base_intermediates)/$d -include $(LOCAL_PATH)/Android.v8.wtf.mk -WEBKIT_SRC_FILES += $(addprefix $d/,$(LOCAL_SRC_FILES)) -endif # JAVASCRIPT_ENGINE == v8 - -# Include source files for WebCore -d := WebCore -LOCAL_PATH := $(BASE_PATH)/$d -JAVASCRIPTCORE_PATH := $(BASE_PATH)/JavaScriptCore -intermediates := $(base_intermediates)/$d -include $(LOCAL_PATH)/Android.mk -ifeq ($(JAVASCRIPT_ENGINE),jsc) -include $(LOCAL_PATH)/Android.jscbindings.mk -endif -ifeq ($(JAVASCRIPT_ENGINE),v8) -include $(LOCAL_PATH)/Android.v8bindings.mk -endif -WEBKIT_SRC_FILES += $(addprefix $d/,$(LOCAL_SRC_FILES)) -LOCAL_C_INCLUDES += $(BINDING_C_INCLUDES) - -# Include the derived source files for WebCore. Uses the same path as -# WebCore -include $(LOCAL_PATH)/Android.derived.mk -ifeq ($(JAVASCRIPT_ENGINE),jsc) -include $(LOCAL_PATH)/Android.derived.jscbindings.mk -endif -ifeq ($(JAVASCRIPT_ENGINE),v8) -include $(LOCAL_PATH)/Android.derived.v8bindings.mk -endif - -# Redefine LOCAL_PATH here so the build system is not confused -LOCAL_PATH := $(BASE_PATH) - -# Define our compiler flags -LOCAL_CFLAGS += -Wno-endif-labels -Wno-import -Wno-format -LOCAL_CFLAGS += -fno-strict-aliasing -LOCAL_CFLAGS += -include "WebCorePrefix.h" -LOCAL_CFLAGS += -fvisibility=hidden - -# Enable JSC JIT if JSC is used and ENABLE_JSC_JIT environment -# variable is set to true -ifeq ($(JAVASCRIPT_ENGINE),jsc) -ifeq ($(ENABLE_JSC_JIT),true) -LOCAL_CFLAGS += -DENABLE_ANDROID_JSC_JIT=1 -endif -endif - -ifeq ($(TARGET_ARCH),arm) -LOCAL_CFLAGS += -Darm -endif - -ifeq ($(ENABLE_SVG),true) -LOCAL_CFLAGS += -DENABLE_SVG=1 -endif - -# Temporary disable SVG_ANIMATION. -ifeq ($(ENABLE_SVG_ANIMATION),true) -LOCAL_CFLAGS += -DENABLE_SVG_ANIMATION=1 -endif - -# LOCAL_LDLIBS is used in simulator builds only and simulator builds are only -# valid on Linux -LOCAL_LDLIBS += -lpthread -ldl - -# Build the list of shared libraries -LOCAL_SHARED_LIBRARIES := \ - libandroid_runtime \ - libnativehelper \ - libsqlite \ - libskia \ - libutils \ - libui \ - libcutils \ - libicuuc \ - libicudata \ - libicui18n \ - libmedia - -# We have to use the android version of libdl. -LOCAL_SHARED_LIBRARIES += libdl - -# Build the list of static libraries -LOCAL_STATIC_LIBRARIES := libxml2 -ifeq ($(JAVASCRIPT_ENGINE),v8) -LOCAL_STATIC_LIBRARIES += libv8 -endif - -# Redefine LOCAL_SRC_FILES to be all the WebKit source files -LOCAL_SRC_FILES := $(WEBKIT_SRC_FILES) - -# Define this for use in other makefiles. -WEBKIT_C_INCLUDES := $(LOCAL_C_INCLUDES) -WEBKIT_CFLAGS := $(LOCAL_CFLAGS) -WEBKIT_GENERATED_SOURCES := $(LOCAL_GENERATED_SOURCES) -WEBKIT_LDLIBS := $(LOCAL_LDLIBS) -WEBKIT_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES) -WEBKIT_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES) - -# Build the library all at once -include $(BUILD_STATIC_LIBRARY) - -ifeq ($(JAVASCRIPT_ENGINE),jsc) -# Now build libjs as a static library. -include $(CLEAR_VARS) -LOCAL_MODULE := libjs -LOCAL_LDLIBS := $(WEBKIT_LDLIBS) -LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES) -LOCAL_STATIC_LIBRARIES := $(WEBKIT_STATIC_LIBRARIES) -LOCAL_CFLAGS := $(WEBKIT_CFLAGS) -# Include source files for JavaScriptCore -d := JavaScriptCore -LOCAL_PATH := $(BASE_PATH)/$d -LOCAL_MODULE_CLASS := STATIC_LIBRARIES -# Cannot use base_intermediates as this is a new module -intermediates := $(call local-intermediates-dir) -include $(LOCAL_PATH)/Android.mk -# Redefine LOCAL_SRC_FILES with the correct prefix -LOCAL_SRC_FILES := $(addprefix $d/,$(LOCAL_SRC_FILES)) -# Use the base path to resolve file names -LOCAL_PATH := $(BASE_PATH) -# Append jsc intermediate include paths to the WebKit include list. -LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES) \ - $(intermediates) \ - $(intermediates)/parser \ - $(intermediates)/runtime \ -# Build libjs -include $(BUILD_STATIC_LIBRARY) -endif # JAVASCRIPT_ENGINE == jsc - -# Now build the shared library using only the exported jni entry point. This -# will strip out any unused code from the entry point. -include $(CLEAR_VARS) -# if you need to make webcore huge (for debugging), enable this line -#LOCAL_PRELINK_MODULE := false -LOCAL_MODULE := libwebcore -LOCAL_LDLIBS := $(WEBKIT_LDLIBS) -LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES) -LOCAL_STATIC_LIBRARIES := libwebcore $(WEBKIT_STATIC_LIBRARIES) -ifeq ($(JAVASCRIPT_ENGINE),jsc) -LOCAL_STATIC_LIBRARIES += libjs -endif -LOCAL_LDFLAGS := -fvisibility=hidden -LOCAL_CFLAGS := $(WEBKIT_CFLAGS) -LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES) -LOCAL_PATH := $(BASE_PATH) -include $(BUILD_SHARED_LIBRARY) diff --git a/Source/WebCore/css/mediaControlsAndroid.css b/Source/WebCore/css/mediaControlsAndroid.css index 77f8b08..614c92f 100644 --- a/Source/WebCore/css/mediaControlsAndroid.css +++ b/Source/WebCore/css/mediaControlsAndroid.css @@ -49,10 +49,7 @@ video:-webkit-full-page-media::-webkit-media-controls-panel { } audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button { - -webkit-appearance: media-mute-button; - display: -webkit-box; - width: 48px; - height: 48px; + display: none; } audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button { diff --git a/Source/WebCore/editing/SelectionController.cpp b/Source/WebCore/editing/SelectionController.cpp index 3eec640..e9bdd6a 100644 --- a/Source/WebCore/editing/SelectionController.cpp +++ b/Source/WebCore/editing/SelectionController.cpp @@ -1562,9 +1562,6 @@ bool SelectionController::isFocusedAndActive() const void SelectionController::updateAppearance() { -#if PLATFORM(ANDROID) - return; -#endif ASSERT(!m_isDragCaretController); #if ENABLE(TEXT_CARET) @@ -1595,6 +1592,10 @@ void SelectionController::updateAppearance() // We need to update style in case the node containing the selection is made display:none. m_frame->document()->updateStyleIfNeeded(); +#if PLATFORM(ANDROID) + return; +#endif + RenderView* view = m_frame->contentRenderer(); if (!view) return; diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp index ae0571c..5cd2ddd 100644 --- a/Source/WebCore/html/HTMLMediaElement.cpp +++ b/Source/WebCore/html/HTMLMediaElement.cpp @@ -2429,7 +2429,7 @@ void HTMLMediaElement::defaultEventHandler(Event* event) // This allows user to click the video area to toggle play/pause state. if (event->type() == eventNames().clickEvent && !hasEventListeners(eventNames().clickEvent)) { - m_userGestureInitiated = true; + m_userGestureInitiated = processingUserGesture(); togglePlayState(); } #endif diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp index 57baee8..b708ad1 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp @@ -141,7 +141,13 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) // only color the invalidated area SkPaint invalPaint; invalPaint.setARGB(color, 0, 255, 0); - canvas.drawIRect(*renderInfo.invalRect, invalPaint); + if (renderInfo.invalRect) + canvas.drawIRect(*renderInfo.invalRect, invalPaint); + else { + SkIRect rect; + rect.set(0, 0, tileSize.width(), tileSize.height()); + canvas.drawIRect(rect, invalPaint); + } // paint the tile boundaries SkPaint paint; @@ -154,6 +160,18 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) canvas.drawLine(0, 0, tileSize.width(), 0, paint); canvas.drawLine(tileSize.width(), 0, tileSize.width(), tileSize.height(), paint); + if (renderInfo.invalRect) { + // if partial inval... + int x = renderInfo.invalRect->fLeft; + int y = renderInfo.invalRect->fTop; + int w = renderInfo.invalRect->width(); + int h = renderInfo.invalRect->height(); + + paint.setARGB(128, 255, 255, 0); + canvas.drawLine(x, y, x + w, y + h, paint); + canvas.drawLine(x, y + h, x + w, y, paint); + } + if (renderInfo.measurePerf) drawTileInfo(&canvas, renderInfo, pictureCount); } diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 76ee1e7..42d02a5 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -54,6 +54,13 @@ #endif // DEBUG +// If the dirty portion of a tile exceeds this ratio, fully repaint. +// Lower values give fewer partial repaints, thus fewer front-to-back +// texture copies (cost will vary by device). It's a tradeoff between +// the rasterization cost and the FBO texture recopy cost when using +// GPU for the transfer queue. +#define MAX_INVAL_AREA 0.6 + namespace WebCore { BaseTile::BaseTile(bool isLayerTile) @@ -369,55 +376,65 @@ void BaseTile::paintBitmap() fullRepaint = true; } - // With SurfaceTexture, just repaint the entire tile if we intersect. - // TODO: Implement the partial invalidate in Surface Texture Mode. - // Such that the code of partial invalidation below is preserved. + // For now, only do full repaint fullRepaint = true; - while (!fullRepaint && !cliperator.done()) { - SkRect realTileRect; - SkRect dirtyRect; - dirtyRect.set(cliperator.rect()); - bool intersect = intersectWithRect(x, y, tileWidth, tileHeight, - scale, dirtyRect, realTileRect); - - if (intersect) { - // initialize finalRealRect to the rounded values of realTileRect - SkIRect finalRealRect; - realTileRect.roundOut(&finalRealRect); - - // stash the int values of the current width and height - const int iWidth = finalRealRect.width(); - const int iHeight = finalRealRect.height(); - - if (iWidth == tileWidth || iHeight == tileHeight) { - fullRepaint = true; - break; + if (!fullRepaint) { + // compute the partial inval area + SkIRect totalRect; + totalRect.set(0, 0, 0, 0); + float tileSurface = tileWidth * tileHeight; + float tileSurfaceCap = MAX_INVAL_AREA * tileSurface; + + // We join all the invals in the same tile for now + while (!fullRepaint && !cliperator.done()) { + SkRect realTileRect; + SkRect dirtyRect; + dirtyRect.set(cliperator.rect()); + bool intersect = intersectWithRect(x, y, tileWidth, tileHeight, + scale, dirtyRect, realTileRect); + if (intersect) { + // initialize finalRealRect to the rounded values of realTileRect + SkIRect finalRealRect; + realTileRect.roundOut(&finalRealRect); + + // stash the int values of the current width and height + const int iWidth = finalRealRect.width(); + const int iHeight = finalRealRect.height(); + + if (iWidth == tileWidth || iHeight == tileHeight) { + fullRepaint = true; + break; + } + + // translate the rect into tile space coordinates + finalRealRect.fLeft = finalRealRect.fLeft % static_cast<int>(tileWidth); + finalRealRect.fTop = finalRealRect.fTop % static_cast<int>(tileHeight); + finalRealRect.fRight = finalRealRect.fLeft + iWidth; + finalRealRect.fBottom = finalRealRect.fTop + iHeight; + totalRect.join(finalRealRect); + float repaintSurface = totalRect.width() * totalRect.height(); + + if (repaintSurface > tileSurfaceCap) { + fullRepaint = true; + break; + } } - // translate the rect into tile space coordinates - finalRealRect.fLeft = finalRealRect.fLeft % static_cast<int>(tileWidth); - finalRealRect.fTop = finalRealRect.fTop % static_cast<int>(tileHeight); - finalRealRect.fRight = finalRealRect.fLeft + iWidth; - finalRealRect.fBottom = finalRealRect.fTop + iHeight; + cliperator.next(); + } - renderInfo.invalRect = &finalRealRect; + if (!fullRepaint) { + renderInfo.invalRect = &totalRect; renderInfo.measurePerf = false; - pictureCount = m_renderer->renderTiledContent(renderInfo); } - - cliperator.next(); } // Do a full repaint if needed if (fullRepaint) { - SkIRect rect; - rect.set(0, 0, tileWidth, tileHeight); - - renderInfo.invalRect = ▭ + renderInfo.invalRect = 0; renderInfo.measurePerf = TilesManager::instance()->getShowVisualIndicator(); - pictureCount = m_renderer->renderTiledContent(renderInfo); } diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/BaseTileTexture.h index 55314c7..67eeeb9 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h @@ -60,6 +60,7 @@ public: TilePainter* m_painter; unsigned int m_picture; bool m_inverted; + IntRect m_inval; }; class BaseTileTexture { diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index efd611b..39d8755 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -36,12 +36,14 @@ #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> - -#ifdef DEBUG - #include <cutils/log.h> #include <wtf/text/CString.h> +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLUtils", __VA_ARGS__) + +#ifdef DEBUG + #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLUtils", __VA_ARGS__) @@ -425,6 +427,10 @@ bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo, bool skipTransfer = false; BaseTile* tilePtr = renderInfo->baseTile; + // TODO: use pure color for partial invals as well + if (renderInfo->invalRect) + return false; + if (tilePtr) { BaseTileTexture* tileTexture = tilePtr->backTexture(); // Check the bitmap, and make everything ready here. @@ -450,8 +456,6 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, { if (!renderInfo) return; - const int x = renderInfo->invalRect->fLeft; - const int y = renderInfo->invalRect->fTop; const SkSize& requiredSize = renderInfo->tileSize; TextureInfo* textureInfo = renderInfo->textureInfo; @@ -459,14 +463,14 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, return; if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) - GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, x, y, bitmap); + GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, bitmap); else { if (!requiredSize.equals(bitmap.width(), bitmap.height())) { XLOG("The bitmap size (%d,%d) does not equal the texture size (%d,%d)", bitmap.width(), bitmap.height(), requiredSize.width(), requiredSize.height()); } - GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, 0, 0, bitmap); + GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, bitmap); textureInfo->m_width = bitmap.width(); textureInfo->m_height = bitmap.height(); @@ -474,14 +478,14 @@ void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, } } -void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap) +void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap) { if (!renderInfo || !renderInfo->textureInfo || !renderInfo->baseTile) return; - TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, x, y, bitmap); + TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap); } void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) @@ -515,7 +519,8 @@ void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GL glDeleteFramebuffers(1, &fboID); } -void GLUtils::updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitmap& bitmap, GLint filter) +void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, + const IntRect& inval, GLint filter) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindTexture(GL_TEXTURE_2D, texture); @@ -524,13 +529,18 @@ void GLUtils::updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitm int internalformat = getInternalFormat(config); int type = getType(config); bitmap.lockPixels(); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, bitmap.width(), bitmap.height(), - internalformat, type, bitmap.getPixels()); + if (inval.isEmpty()) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(), + internalformat, type, bitmap.getPixels()); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), inval.width(), inval.height(), + internalformat, type, bitmap.getPixels()); + } bitmap.unlockPixels(); if (GLUtils::checkGlError("glTexSubImage2D")) { XLOG("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d," - " x %d, y %d, internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", - bitmap.width(), bitmap.height(), x, y, internalformat, type, bitmap.getPixels()); + " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", + bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h index 3475760..b198d35 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ b/Source/WebCore/platform/graphics/android/GLUtils.h @@ -74,12 +74,12 @@ public: static GLuint createBaseTileGLTexture(int width, int height); static void createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter = GL_LINEAR); - static void updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, const IntRect&, GLint filter = GL_LINEAR); static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); - static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap); + static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap); static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix); static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor); diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp index 0c92de4..4b6d2de 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp @@ -112,8 +112,14 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can device->unref(); - // ensure the canvas origin is translated to the coordinates of our inval rect - canvas->translate(-renderInfo.invalRect->fLeft, -renderInfo.invalRect->fTop); + // If we have a partially painted bitmap + if (renderInfo.invalRect) { + SkRect clipRect = SkRect::MakeWH(renderInfo.invalRect->width(), + renderInfo.invalRect->height()); + // ensure the canvas origin is translated to the coordinates of our inval rect + canvas->clipRect(clipRect); + canvas->translate(-renderInfo.invalRect->fLeft, -renderInfo.invalRect->fTop); + } } void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index 56d79a1..00f851b 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -107,7 +107,8 @@ void TransferQueue::initGLResources(int width, int height) glGenTextures(1, &m_sharedSurfaceTextureId); m_sharedSurfaceTexture = #if GPU_UPLOAD_WITHOUT_DRAW - new android::SurfaceTexture(m_sharedSurfaceTextureId, true, GL_TEXTURE_2D); + new android::SurfaceTexture(m_sharedSurfaceTextureId, true, + GL_TEXTURE_2D, false); #else new android::SurfaceTexture(m_sharedSurfaceTextureId); #endif @@ -162,20 +163,46 @@ bool TransferQueue::checkObsolete(const TileTransferData* data) } void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, + BaseTileTexture* frontTex, GLuint srcTexId, GLenum srcTexTarget, int index) { #if GPU_UPLOAD_WITHOUT_DRAW glBindFramebuffer(GL_FRAMEBUFFER, fboID); + glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId); + + int textureWidth = destTex->getSize().width(); + int textureHeight = destTex->getSize().height(); + + IntRect inval = m_transferQueue[index].tileInfo.m_inval; + bool partialInval = !inval.isEmpty(); + + if (partialInval && frontTex) { + // recopy the previous texture to the new one, as + // the partial update will not cover the entire texture + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + frontTex->m_ownTextureId, + 0); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, + textureWidth, textureHeight); + } + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTexId, 0); - glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, - destTex->getSize().width(), - destTex->getSize().height()); + + if (!partialInval) { + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, + textureWidth, textureHeight); + } else { + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), 0, 0, + inval.width(), inval.height()); + } + #else // Then set up the FBO and copy the SurfTex content in. glBindFramebuffer(GL_FRAMEBUFFER, fboID); @@ -356,8 +383,14 @@ void TransferQueue::updateDirtyBaseTiles() // Save the needed info, update the Surf Tex, clean up the item in // the queue. Then either move on to next item or copy the content. BaseTileTexture* destTexture = 0; - if (!obsoleteBaseTile) + BaseTileTexture* frontTexture = 0; + if (!obsoleteBaseTile) { destTexture = m_transferQueue[index].savedBaseTilePtr->backTexture(); + // while destTexture is guaranteed to not be null, frontTexture + // might be (first transfer) + frontTexture = m_transferQueue[index].savedBaseTilePtr->frontTexture(); + } + if (m_transferQueue[index].uploadType == GpuUpload) { status_t result = m_sharedSurfaceTexture->updateTexImage(); if (result != OK) @@ -376,14 +409,15 @@ void TransferQueue::updateDirtyBaseTiles() if (m_transferQueue[index].uploadType == CpuUpload) { // Here we just need to upload the bitmap content to the GL Texture - GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, 0, 0, - *m_transferQueue[index].bitmap); + GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, + *m_transferQueue[index].bitmap, + m_transferQueue[index].tileInfo.m_inval); } else { if (!usedFboForUpload) { saveGLState(); usedFboForUpload = true; } - blitTileFromQueue(m_fboID, destTexture, + blitTileFromQueue(m_fboID, destTexture, frontTexture, m_sharedSurfaceTextureId, m_sharedSurfaceTexture->getCurrentTextureTarget(), index); @@ -420,9 +454,9 @@ void TransferQueue::updateDirtyBaseTiles() } void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, - int x, int y, const SkBitmap& bitmap) + const SkBitmap& bitmap) { - if (!tryUpdateQueueWithBitmap(renderInfo, x, y, bitmap)) { + if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) { // failed placing bitmap in queue, discard tile's texture so it will be // re-enqueued (and repainted) BaseTile* tile = renderInfo->baseTile; @@ -432,7 +466,7 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, } bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, - int x, int y, const SkBitmap& bitmap) + const SkBitmap& bitmap) { // This lock need to cover the full update since it is possible that queue // will be cleaned up in the middle of this update without the lock. @@ -462,9 +496,10 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, int bpp = 4; // Now we only deal with RGBA8888 format. int width = TilesManager::instance()->tileWidth(); int height = TilesManager::instance()->tileHeight(); - if (!x && !y && bitmap.width() == width && bitmap.height() == height) { + if (bitmap.width() == width && bitmap.height() == height) { bitmap.lockPixels(); uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); + if (buffer.stride != bitmap.width()) // Copied line by line since we need to handle the offsets and stride. for (row = 0 ; row < bitmap.height(); row ++) { @@ -476,9 +511,6 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); bitmap.unlockPixels(); - } else { - // TODO: implement the partial invalidate here! - XLOG("ERROR: don't expect to get here yet before we support partial inval"); } ANativeWindow_unlockAndPost(m_ANW.get()); @@ -517,6 +549,15 @@ void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, // Now fill the tileInfo. TextureTileInfo* textureInfo = &(data->tileInfo); + IntRect inval(0, 0, 0, 0); + if (renderInfo->invalRect) { + inval.setX(renderInfo->invalRect->fLeft); + inval.setY(renderInfo->invalRect->fTop); + inval.setWidth(renderInfo->invalRect->width()); + inval.setHeight(renderInfo->invalRect->height()); + } + textureInfo->m_inval = inval; + textureInfo->m_x = renderInfo->x; textureInfo->m_y = renderInfo->y; textureInfo->m_scale = renderInfo->scale; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h index a18d448..ec3e5e2 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -119,7 +119,7 @@ public: void initGLResources(int width, int height); // insert the bitmap into the queue, mark the tile dirty if failing - void updateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y, + void updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); void addItemInTransferQueue(const TileRenderInfo* info, @@ -151,7 +151,7 @@ public: private: // return true if successfully inserted into queue - bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y, + bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); bool getHasGLContext(); void setHasGLContext(bool hasContext); @@ -172,6 +172,7 @@ private: void cleanupPendingDiscard(); void blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, + BaseTileTexture* frontTex, GLuint srcTexId, GLenum srcTexTarget, int index); diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index fd1a833..1fb3c75 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -283,7 +283,6 @@ struct WebViewCore::JavaGlue { jmethodID m_restoreScale; jmethodID m_needTouchEvents; jmethodID m_requestKeyboard; - jmethodID m_requestKeyboardWithSelection; jmethodID m_exceededDatabaseQuota; jmethodID m_reachedMaxAppCacheSize; jmethodID m_populateVisitedLinks; @@ -417,7 +416,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(FF)V"); m_javaGlue->m_needTouchEvents = GetJMethod(env, clazz, "needTouchEvents", "(Z)V"); m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V"); - m_javaGlue->m_requestKeyboardWithSelection = GetJMethod(env, clazz, "requestKeyboardWithSelection", "(IIII)V"); m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;JJ)V"); m_javaGlue->m_reachedMaxAppCacheSize = GetJMethod(env, clazz, "reachedMaxAppCacheSize", "(J)V"); m_javaGlue->m_populateVisitedLinks = GetJMethod(env, clazz, "populateVisitedLinks", "()V"); @@ -447,7 +445,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m #endif m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V"); m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V"); - m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(Ljava/lang/String;II)V"); + m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;II)V"); env->DeleteLocalRef(clazz); env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this); @@ -1156,22 +1154,6 @@ void WebViewCore::needTouchEvents(bool need) #endif } -void WebViewCore::requestKeyboardWithSelection(const WebCore::Node* node, - int selStart, int selEnd) -{ - DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); - ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); - - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject javaObject = m_javaGlue->object(env); - if (!javaObject.get()) - return; - env->CallVoidMethod(javaObject.get(), - m_javaGlue->m_requestKeyboardWithSelection, - reinterpret_cast<int>(node), selStart, selEnd, m_textGeneration); - checkException(env); -} - void WebViewCore::requestKeyboard(bool showKeyboard) { DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); @@ -1660,48 +1642,55 @@ static IntRect getAbsoluteBoundingBox(Node* node) { return rect; } +WebCore::Frame* WebViewCore::focusedFrame() const +{ + return m_mainFrame->page()->focusController()->focusedOrMainFrame(); +} + VisiblePosition WebViewCore::visiblePositionForContentPoint(int x, int y) { - IntPoint point(x, y); + return visiblePositionForContentPoint(IntPoint(x, y)); +} +VisiblePosition WebViewCore::visiblePositionForContentPoint(const IntPoint& point) +{ // Hit test of this kind required for this to work inside input fields - HitTestRequest request(HitTestRequest::Active | HitTestRequest::MouseMove | HitTestRequest::ReadOnly); - - // Look for the inner-most frame containing the hit. Its document - // contains the document with the selected text. - Frame* frame = m_mainFrame; - Frame* hitFrame = m_mainFrame; - Node* node = 0; - IntPoint localPoint = point; - do { - HitTestResult result(localPoint); - frame = hitFrame; - frame->document()->renderView()->layer()->hitTest(request, result); - node = result.innerNode(); - if (!node) - return VisiblePosition(); - - if (node->isFrameOwnerElement()) - hitFrame = static_cast<HTMLFrameOwnerElement*>(node)->contentFrame(); - localPoint = result.localPoint(); - } while (hitFrame && hitFrame != frame); + HitTestRequest request(HitTestRequest::Active + | HitTestRequest::MouseMove + | HitTestRequest::ReadOnly + | HitTestRequest::IgnoreClipping); + HitTestResult result(point); + focusedFrame()->document()->renderView()->layer()->hitTest(request, result); + // Matching the logic in MouseEventWithHitTestResults::targetNode() + Node* node = result.innerNode(); + if (!node) + return VisiblePosition(); Element* element = node->parentElement(); if (!node->inDocument() && element && element->inDocument()) node = element; - RenderObject* renderer = node->renderer(); - return renderer->positionForPoint(localPoint); + return node->renderer()->positionForPoint(result.localPoint()); } void WebViewCore::selectWordAt(int x, int y) { - IntPoint point(x, y); + HitTestResult hoverResult; + moveMouse(m_mainFrame, x, y, &hoverResult); + if (hoverResult.innerNode()) { + Node* node = hoverResult.innerNode(); + Frame* frame = node->document()->frame(); + Page* page = m_mainFrame->document()->page(); + page->focusController()->setFocusedFrame(frame); + } + + IntPoint point = convertGlobalContentToFrameContent(IntPoint(x, y)); // Hit test of this kind required for this to work inside input fields HitTestRequest request(HitTestRequest::Active); HitTestResult result(point); - m_mainFrame->document()->renderView()->layer()->hitTest(request, result); + + focusedFrame()->document()->renderView()->layer()->hitTest(request, result); // Matching the logic in MouseEventWithHitTestResults::targetNode() Node* node = result.innerNode(); @@ -1711,7 +1700,7 @@ void WebViewCore::selectWordAt(int x, int y) if (!node->inDocument() && element && element->inDocument()) node = element; - SelectionController* sc = m_mainFrame->selection(); + SelectionController* sc = focusedFrame()->selection(); if (!sc->contains(point) && (node->isContentEditable() || node->isTextNode()) && !result.isLiveLink() && node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true))) { VisiblePosition pos(node->renderer()->positionForPoint(result.localPoint())); @@ -1775,22 +1764,11 @@ void WebViewCore::layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& off } } -void setCaretInfo(const VisiblePosition& pos, SelectText::HandleId handle, - SelectText* target) -{ - IntPoint offset; - LayerAndroid* layer = 0; - IntRect rect = pos.absoluteCaretBounds(); - int layerId = WebViewCore::platformLayerIdFromNode(pos.deepEquivalent().anchorNode(), &layer); - WebViewCore::layerToAbsoluteOffset(layer, offset); - rect.move(-offset.x(), -offset.y()); - target->setCaretRect(handle, rect); - target->setCaretLayerId(handle, layerId); -} - SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) { - if (!selection.isRange()) + // We need to agressively check to see if this is an empty selection to prevent + // accidentally entering text selection mode + if (!selection.isRange() || !comparePositions(selection.start(), selection.end())) return 0; RefPtr<Range> range = selection.firstRange(); @@ -1799,9 +1777,14 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) if (!startContainer || !endContainer) return 0; + if (startContainer == endContainer && range->startOffset() == range->endOffset()) + return 0; SelectText* selectTextContainer = new SelectText(); + IntPoint frameOffset = convertGlobalContentToFrameContent(IntPoint()); + IntRect startHandle; + IntRect endHandle; Node* stopNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) { RenderObject* r = node->renderer(); @@ -1811,33 +1794,59 @@ SelectText* WebViewCore::createSelectText(const VisibleSelection& selection) int startOffset = node == startContainer ? range->startOffset() : 0; int endOffset = node == endContainer ? range->endOffset() : numeric_limits<int>::max(); LayerAndroid* layer = 0; - platformLayerIdFromNode(node, &layer); + int layerId = platformLayerIdFromNode(node, &layer); Vector<IntRect> rects; renderText->absoluteRectsForRange(rects, startOffset, endOffset, true); - selectTextContainer->addHighlightRegion(layer, rects); + if (rects.size()) { + IntPoint offset; + layerToAbsoluteOffset(layer, offset); + endHandle = rects[rects.size() - 1]; + endHandle.move(-offset.x(), -offset.y()); + selectTextContainer->setCaretLayerId(SelectText::EndHandle, layerId); + if (startHandle.isEmpty()) { + startHandle = rects[0]; + startHandle.move(-offset.x(), -offset.y()); + selectTextContainer->setCaretLayerId(SelectText::StartHandle, layerId); + } + } + selectTextContainer->addHighlightRegion(layer, rects, frameOffset); } IntRect caretRect; int layerId; selectTextContainer->setBaseFirst(selection.isBaseFirst()); - ALOGD("isBaseFirst: %s", selectTextContainer->isBaseFirst() ? "true" : "false"); - setCaretInfo(selection.visibleStart(), SelectText::StartHandle, selectTextContainer); - setCaretInfo(selection.visibleEnd(), SelectText::EndHandle, selectTextContainer); + + // Squish the handle rects + startHandle.setWidth(1); + endHandle.move(endHandle.width() - 1, 0); + endHandle.setWidth(1); + startHandle.move(-frameOffset.x(), -frameOffset.y()); + selectTextContainer->setCaretRect(SelectText::StartHandle, startHandle); + endHandle.move(-frameOffset.x(), -frameOffset.y()); + selectTextContainer->setCaretRect(SelectText::EndHandle, endHandle); selectTextContainer->setText(range->text()); return selectTextContainer; } +IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point) +{ + IntPoint frameOffset(-m_scrollOffsetX, -m_scrollOffsetY); + frameOffset = focusedFrame()->view()->windowToContents(frameOffset); + return IntPoint(point.x() + frameOffset.x(), point.y() + frameOffset.y()); +} + void WebViewCore::selectText(int startX, int startY, int endX, int endY) { - SelectionController* sc = m_mainFrame->selection(); - VisiblePosition startPosition(visiblePositionForContentPoint(startX, startY)); - VisiblePosition endPosition(visiblePositionForContentPoint(endX, endY)); + SelectionController* sc = focusedFrame()->selection(); + IntPoint startPoint = convertGlobalContentToFrameContent(IntPoint(startX, startY)); + VisiblePosition startPosition(visiblePositionForContentPoint(startPoint)); + IntPoint endPoint = convertGlobalContentToFrameContent(IntPoint(endX, endY)); + VisiblePosition endPosition(visiblePositionForContentPoint(endPoint)); - if (startPosition.isNull() || endPosition.isNull() || startPosition == endPosition) { + if (startPosition.isNull() || endPosition.isNull() || startPosition == endPosition) return; - } // Ensure startPosition is before endPosition if (comparePositions(startPosition, endPosition) > 0) @@ -1865,9 +1874,8 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY) } VisibleSelection selection(startPosition, endPosition); - if (selection.isRange() && sc->shouldChangeSelection(selection)) { + if (selection.isRange() && sc->shouldChangeSelection(selection)) sc->setSelection(selection); - } } // get the highlight rectangles for the touch point (x, y) with the slop @@ -2336,7 +2344,7 @@ void WebViewCore::moveFocus(WebCore::Frame* frame, WebCore::Node* node) } // Update mouse position -void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y) +void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y, HitTestResult* hoveredNode) { DBG_NAV_LOGD("frame=%p x=%d y=%d scrollOffset=(%d,%d)", frame, x, y, m_scrollOffsetX, m_scrollOffsetY); @@ -2349,7 +2357,7 @@ void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y) WebCore::PlatformMouseEvent mouseEvent(m_mousePos, m_mousePos, WebCore::NoButton, WebCore::MouseEventMoved, 1, false, false, false, false, WTF::currentTime()); - frame->eventHandler()->handleMouseMoveEvent(mouseEvent); + frame->eventHandler()->handleMouseMoveEvent(mouseEvent, hoveredNode); #if ENABLE(ANDROID_NAVCACHE) updateCacheOnNodeChange(); #endif @@ -2357,12 +2365,8 @@ void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y) Position WebViewCore::getPositionForOffset(Node* node, int offset) { - Position positionInNode(node, 0); - Node* highest = highestEditableRoot(positionInNode); - if (!highest) - highest = node; - Position start = firstPositionInNode(highest); - Position end = lastPositionInNode(highest); + Position start = firstPositionInNode(node); + Position end = lastPositionInNode(node); Document* document = node->document(); PassRefPtr<Range> range = Range::create(document, start, end); WebCore::CharacterIterator iterator(range.get()); @@ -3325,7 +3329,11 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event) WebFrame* webFrame = WebFrame::getWebFrame(frame); eventHandler = frame->eventHandler(); VisibleSelection old = frame->selection()->selection(); + EditorClientAndroid* client = static_cast<EditorClientAndroid*>( + m_mainFrame->editor()->client()); + client->setUiGeneratedSelectionChange(true); bool handled = eventHandler->keyEvent(event); + client->setUiGeneratedSelectionChange(false); if (isContentEditable(focusNode)) { // keyEvent will return true even if the contentEditable did not // change its selection. In the case that it does not, we want to @@ -3563,8 +3571,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node m_frameCacheOutOfDate = true; updateFrameCache(); #endif - requestKeyboardWithSelection(focusNode, rtc->selectionStart(), - rtc->selectionEnd()); + initEditField(focusNode); } } else if (!fake) { requestKeyboard(false); @@ -3575,7 +3582,6 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node // input is needed. if (isContentEditable(focusNode)) { initEditField(focusNode); - requestKeyboard(true); } else if (!nodeIsPlugin(focusNode)) { clearTextEntry(); } @@ -3597,9 +3603,10 @@ void WebViewCore::initEditField(Node* node) AutoJObject javaObject = m_javaGlue->object(env); if (!javaObject.get()) return; + m_textGeneration = 0; jstring fieldText = wtfStringToJstring(env, text, true); env->CallVoidMethod(javaObject.get(), m_javaGlue->m_initEditField, - fieldText, start, end); + reinterpret_cast<int>(node), fieldText, start, end); checkException(env); } @@ -3867,8 +3874,7 @@ void WebViewCore::getSelectionOffsets(Node* node, int& start, int& end) SelectionController* selector = frame->selection(); Position selectionStart = selector->start(); Position selectionEnd = selector->end(); - Node* editable = highestEditableRoot(selectionStart); - Position startOfNode = firstPositionInNode(editable); + Position startOfNode = firstPositionInNode(node); RefPtr<Range> startRange = Range::create(document, startOfNode, selectionStart); start = TextIterator::rangeLength(startRange.get(), true); @@ -3887,13 +3893,10 @@ String WebViewCore::getInputText(Node* node) else { // It must be content editable field. Position inNode(node, 0); - Node* editable = highestEditableRoot(inNode); - if (editable) { - Position start = firstPositionInNode(editable); - Position end = lastPositionInNode(editable); - VisibleSelection allEditableText(start, end); - text = allEditableText.firstRange()->text(); - } + Position start = firstPositionInNode(node); + Position end = lastPositionInNode(node); + VisibleSelection allEditableText(start, end); + text = allEditableText.firstRange()->text(); } return text; } @@ -3909,7 +3912,7 @@ void WebViewCore::updateTextSelection() int end = 0; if (focusNode) getSelectionOffsets(focusNode, start, end); - SelectText* selectText = createSelectText(m_mainFrame->selection()->selection()); + SelectText* selectText = createSelectText(focusedFrame()->selection()->selection()); env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode), start, end, m_textGeneration, selectText); @@ -5002,7 +5005,7 @@ static void SelectText(JNIEnv* env, jobject obj, jint nativeClass, static void ClearSelection(JNIEnv* env, jobject obj, jint nativeClass) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - viewImpl->mainFrame()->selection()->clear(); + viewImpl->focusedFrame()->selection()->clear(); } static void SelectWordAt(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y) @@ -5014,7 +5017,7 @@ static void SelectWordAt(JNIEnv* env, jobject obj, jint nativeClass, jint x, jin static void SelectAll(JNIEnv* env, jobject obj, jint nativeClass) { WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); - viewImpl->mainFrame()->selection()->selectAll(); + viewImpl->focusedFrame()->selection()->selectAll(); } // ---------------------------------------------------------------------------- diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index cb345dd..034229d 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -305,7 +305,7 @@ namespace android { void recordPicture(SkPicture* picture); void moveFocus(WebCore::Frame* frame, WebCore::Node* node); - void moveMouse(WebCore::Frame* frame, int x, int y); + void moveMouse(WebCore::Frame* frame, int x, int y, HitTestResult* hoveredNode = 0); void moveMouseIfLatest(int moveGeneration, WebCore::Frame* frame, int x, int y); @@ -547,6 +547,7 @@ namespace android { float scale() const { return m_scale; } float textWrapScale() const { return m_screenWidth * m_scale / m_textWrapWidth; } WebCore::Frame* mainFrame() const { return m_mainFrame; } + WebCore::Frame* focusedFrame() const; void updateCursorBounds(const CachedRoot* root, const CachedFrame* cachedFrame, const CachedNode* cachedNode); @@ -607,6 +608,9 @@ namespace android { void selectText(int startX, int startY, int endX, int endY); void selectWordAt(int x, int y); + // Converts from the global content coordinates that WebView sends + // to frame-local content coordinates using the focused frame + IntPoint convertGlobalContentToFrameContent(const IntPoint& point); static void layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& offset); /** @@ -675,13 +679,12 @@ namespace android { Node* getImplicitBoundaryNode(Node* node, unsigned offset, int direction); /** * Calls into java to reset the text edit field with the - * current contents and selection. This currently works only with - * content-editable fields. + * current contents and selection. */ void initEditField(Node* node); /** * Returns the offsets of the selection area for both normal text - * fields and content-editable fields. start and end are modified + * fields and content editable fields. start and end are modified * by this method. */ static void getSelectionOffsets(Node* node, int& start, int& end); @@ -702,14 +705,14 @@ namespace android { static void setSelection(Node* node, int start, int end); /** * Returns the Position for the given offset for an editable - * field. If node is editable the offset relative to the highest - * editable node. If it is not editable, the offset is relative to node. + * field. The offset is relative to the node start. */ static WebCore::Position getPositionForOffset(Node* node, int offset); VisiblePosition visiblePositionForContentPoint(int x, int y); + VisiblePosition visiblePositionForContentPoint(const IntPoint& point); void selectWordAroundPosition(Frame* frame, VisiblePosition pos); - static SelectText* createSelectText(const VisibleSelection&); + SelectText* createSelectText(const VisibleSelection&); // called from constructor, to add this to a global list static void addInstance(WebViewCore*); diff --git a/Source/WebKit/android/nav/DrawExtra.cpp b/Source/WebKit/android/nav/DrawExtra.cpp index 564cc21..2f57dc1 100644 --- a/Source/WebKit/android/nav/DrawExtra.cpp +++ b/Source/WebKit/android/nav/DrawExtra.cpp @@ -51,7 +51,8 @@ SkRegion* RegionLayerDrawExtra::getHighlightRegionsForLayer(const LayerAndroid* return m_highlightRegions.get(layerId); } -void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects) +void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects, + const IntPoint& additionalOffset) { if (rects.isEmpty()) return; @@ -61,7 +62,7 @@ void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const V region = new SkRegion(); m_highlightRegions.set(layerId, region); } - IntPoint offset; + IntPoint offset = additionalOffset; WebViewCore::layerToAbsoluteOffset(layer, offset); for (size_t i = 0; i < rects.size(); i++) { IntRect r = rects.at(i); diff --git a/Source/WebKit/android/nav/DrawExtra.h b/Source/WebKit/android/nav/DrawExtra.h index 0cee861..83e7dcd 100644 --- a/Source/WebKit/android/nav/DrawExtra.h +++ b/Source/WebKit/android/nav/DrawExtra.h @@ -65,7 +65,8 @@ public: RegionLayerDrawExtra(); virtual ~RegionLayerDrawExtra(); - void addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects); + void addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects, + const IntPoint& additionalOffset = IntPoint()); virtual void draw(SkCanvas*, LayerAndroid*); virtual void drawGL(GLExtras*, const LayerAndroid*); diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 8e819fb..c12adb5 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -1418,15 +1418,16 @@ int getHandleLayerId(SelectText::HandleId handleId, SkIRect& cursorRect) { if (!selectText) return -1; int layerId = selectText->caretLayerId(handleId); - const IntRect& r = selectText->caretRect(handleId); - cursorRect.set(r.x(), r.y(), r.maxX(), r.maxY()); + IntRect rect = selectText->caretRect(handleId); if (layerId != -1) { + // We need to make sure the drawTransform is up to date as this is + // called before a draw() or drawGL() + m_baseLayer->updateLayerPositions(m_visibleRect); LayerAndroid* root = compositeRoot(); LayerAndroid* layer = root ? root->findById(layerId) : 0; - IntPoint offset; - WebViewCore::layerToAbsoluteOffset(layer, offset); - cursorRect.offset(offset.x(), offset.y()); + rect = layer->drawTransform()->mapRect(rect); } + cursorRect.set(rect.x(), rect.y(), rect.maxX(), rect.maxY()); return layerId; } |