summaryrefslogtreecommitdiffstats
path: root/WebKit/android/jni/WebViewCore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android/jni/WebViewCore.cpp')
-rw-r--r--WebKit/android/jni/WebViewCore.cpp681
1 files changed, 474 insertions, 207 deletions
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 1562775..d3e32d3 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -29,6 +29,7 @@
#include "WebViewCore.h"
#include "AtomicString.h"
+#include "BaseLayerAndroid.h"
#include "CachedNode.h"
#include "CachedRoot.h"
#include "Chrome.h"
@@ -37,6 +38,7 @@
#include "DatabaseTracker.h"
#include "Document.h"
#include "DOMWindow.h"
+#include "DOMSelection.h"
#include "Element.h"
#include "Editor.h"
#include "EditorClientAndroid.h"
@@ -65,9 +67,9 @@
#include "HTMLSelectElement.h"
#include "HTMLTextAreaElement.h"
#include "HistoryItem.h"
+#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "InlineTextBox.h"
-#include "KeyboardCodes.h"
#include "Navigator.h"
#include "Node.h"
#include "NodeList.h"
@@ -79,7 +81,9 @@
#include "PluginView.h"
#include "Position.h"
#include "ProgressTracker.h"
+#include "Range.h"
#include "RenderBox.h"
+#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderPart.h"
#include "RenderText.h"
@@ -101,6 +105,7 @@
#include "TypingCommand.h"
#include "WebCoreFrameBridge.h"
#include "WebFrameView.h"
+#include "WindowsKeyboardCodes.h"
#include "android_graphics.h"
#include <JNIHelp.h>
@@ -109,9 +114,9 @@
#include <wtf/CurrentTime.h>
#if USE(V8)
-#include "CString.h"
#include "ScriptController.h"
#include "V8Counters.h"
+#include <wtf/text/CString.h>
#endif
#if DEBUG_NAV_UI
@@ -125,7 +130,7 @@
#ifdef ANDROID_DOM_LOGGING
#include "AndroidLog.h"
#include "RenderTreeAsText.h"
-#include "CString.h"
+#include <wtf/text/CString.h>
FILE* gDomTreeFile = 0;
FILE* gRenderTreeFile = 0;
@@ -226,13 +231,10 @@ struct WebViewCore::JavaGlue {
jmethodID m_updateViewport;
jmethodID m_sendNotifyProgressFinished;
jmethodID m_sendViewInvalidate;
- jmethodID m_sendImmediateRepaint;
- jmethodID m_setRootLayer;
jmethodID m_updateTextfield;
jmethodID m_updateTextSelection;
jmethodID m_clearTextEntry;
jmethodID m_restoreScale;
- jmethodID m_restoreScreenWidthScale;
jmethodID m_needTouchEvents;
jmethodID m_requestKeyboard;
jmethodID m_requestKeyboardWithSelection;
@@ -253,6 +255,7 @@ struct WebViewCore::JavaGlue {
jmethodID m_showRect;
jmethodID m_centerFitRect;
jmethodID m_setScrollbarModes;
+ jmethodID m_setInstallableWebApp;
AutoJObject object(JNIEnv* env) {
return getRealObject(env, m_obj);
}
@@ -272,7 +275,6 @@ static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const
Mutex WebViewCore::gFrameCacheMutex;
Mutex WebViewCore::gButtonMutex;
Mutex WebViewCore::gCursorBoundsMutex;
-Mutex WebViewCore::m_contentMutex;
WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* mainframe)
: m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
@@ -289,8 +291,8 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_maxYScroll = 240/4;
m_textGeneration = 0;
m_screenWidth = 320;
+ m_textWrapWidth = 320;
m_scale = 1;
- m_screenWidthScale = 1;
#if ENABLE(TOUCH_EVENTS)
m_forwardingTouchEvents = false;
#endif
@@ -306,7 +308,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_scrollBy = GetJMethod(env, clazz, "contentScrollBy", "(IIZ)V");
m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V");
m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V");
- m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "()Ljava/lang/String;");
+ m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "(Ljava/lang/String;)Ljava/lang/String;");
m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[II)V");
m_javaGlue->m_jsAlert = GetJMethod(env, clazz, "jsAlert", "(Ljava/lang/String;Ljava/lang/String;)V");
m_javaGlue->m_jsConfirm = GetJMethod(env, clazz, "jsConfirm", "(Ljava/lang/String;Ljava/lang/String;)Z");
@@ -317,13 +319,10 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_updateViewport = GetJMethod(env, clazz, "updateViewport", "()V");
m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V");
m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V");
- m_javaGlue->m_sendImmediateRepaint = GetJMethod(env, clazz, "sendImmediateRepaint", "()V");
- m_javaGlue->m_setRootLayer = GetJMethod(env, clazz, "setRootLayer", "(I)V");
m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V");
m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
- m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(I)V");
- m_javaGlue->m_restoreScreenWidthScale = GetJMethod(env, clazz, "restoreScreenWidthScale", "(I)V");
+ m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(II)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");
@@ -344,6 +343,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
m_javaGlue->m_centerFitRect = GetJMethod(env, clazz, "centerFitRect", "(IIII)V");
m_javaGlue->m_setScrollbarModes = GetJMethod(env, clazz, "setScrollbarModes", "(II)V");
+ m_javaGlue->m_setInstallableWebApp = GetJMethod(env, clazz, "setInstallableWebApp", "()V");
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
@@ -485,7 +485,8 @@ void WebViewCore::recordPicture(SkPicture* picture)
WebCore::PlatformGraphicsContext pgc(arp.getRecordingCanvas(), &buttons);
WebCore::GraphicsContext gc(&pgc);
- view->platformWidget()->draw(&gc, WebCore::IntRect(0, 0, INT_MAX, INT_MAX));
+ view->platformWidget()->draw(&gc, WebCore::IntRect(0, 0,
+ view->contentsWidth(), view->contentsHeight()));
gButtonMutex.lock();
updateButtonList(&buttons);
@@ -589,6 +590,9 @@ void WebViewCore::recordPictureSet(PictureSet* content)
height = view->contentsHeight();
}
+ if (cacheBuilder().pictureSetDisabled())
+ content->clear();
+
content->checkDimensions(width, height, &m_addInval);
// The inval region may replace existing pictures. The existing pictures
@@ -741,50 +745,11 @@ void WebViewCore::updateCursorBounds(const CachedRoot* root,
void WebViewCore::clearContent()
{
DBG_SET_LOG("");
- m_contentMutex.lock();
m_content.clear();
- m_contentMutex.unlock();
m_addInval.setEmpty();
m_rebuildInval.setEmpty();
}
-void WebViewCore::copyContentToPicture(SkPicture* picture)
-{
- DBG_SET_LOG("start");
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- m_contentMutex.unlock();
-
- int w = copyContent.width();
- int h = copyContent.height();
- copyContent.draw(picture->beginRecording(w, h, PICT_RECORD_FLAGS));
- picture->endRecording();
- DBG_SET_LOG("end");
-}
-
-bool WebViewCore::drawContent(SkCanvas* canvas, SkColor color)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewUIDrawTimeCounter);
-#endif
- DBG_SET_LOG("start");
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- m_contentMutex.unlock();
- int sc = canvas->save(SkCanvas::kClip_SaveFlag);
- SkRect clip;
- clip.set(0, 0, copyContent.width(), copyContent.height());
- canvas->clipRect(clip, SkRegion::kDifference_Op);
- canvas->drawColor(color);
- canvas->restoreToCount(sc);
- bool tookTooLong = copyContent.draw(canvas);
- m_contentMutex.lock();
- m_content.setDrawTimes(copyContent);
- m_contentMutex.unlock();
- DBG_SET_LOG("end");
- return tookTooLong;
-}
-
bool WebViewCore::focusBoundsChanged()
{
bool result = m_focusBoundsChanged;
@@ -792,18 +757,6 @@ bool WebViewCore::focusBoundsChanged()
return result;
}
-bool WebViewCore::pictureReady()
-{
- bool done;
- m_contentMutex.lock();
- PictureSet copyContent = PictureSet(m_content);
- done = m_progressDone;
- m_contentMutex.unlock();
- DBG_NAV_LOGD("done=%s empty=%s", done ? "true" : "false",
- copyContent.isEmpty() ? "true" : "false");
- return done || !copyContent.isEmpty();
-}
-
SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval)
{
WebCore::FrameView* view = m_mainFrame->view();
@@ -851,48 +804,52 @@ void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
pictureSet->validate(__FUNCTION__);
}
-bool WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
+BaseLayerAndroid* WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
{
DBG_SET_LOG("start");
float progress = (float) m_mainFrame->page()->progress()->estimatedProgress();
- m_contentMutex.lock();
- PictureSet contentCopy(m_content);
m_progressDone = progress <= 0.0f || progress >= 1.0f;
- m_contentMutex.unlock();
- recordPictureSet(&contentCopy);
- if (!m_progressDone && contentCopy.isEmpty()) {
+ recordPictureSet(&m_content);
+ if (!m_progressDone && m_content.isEmpty()) {
DBG_SET_LOGD("empty (progress=%g)", progress);
- return false;
+ return 0;
}
region->set(m_addInval);
m_addInval.setEmpty();
region->op(m_rebuildInval, SkRegion::kUnion_Op);
m_rebuildInval.setEmpty();
- m_contentMutex.lock();
- contentCopy.setDrawTimes(m_content);
- m_content.set(contentCopy);
point->fX = m_content.width();
point->fY = m_content.height();
- m_contentMutex.unlock();
DBG_SET_LOGD("region={%d,%d,r=%d,b=%d}", region->getBounds().fLeft,
region->getBounds().fTop, region->getBounds().fRight,
region->getBounds().fBottom);
DBG_SET_LOG("end");
- return true;
+
+ BaseLayerAndroid* base = new BaseLayerAndroid();
+ base->setContent(m_content);
+
+#if USE(ACCELERATED_COMPOSITING)
+ // We update the layers
+ ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
+ GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
+ if (root) {
+ root->notifyClientAnimationStarted();
+ LayerAndroid* copyLayer = new LayerAndroid(*root->contentLayer());
+ base->addChild(copyLayer);
+ copyLayer->unref();
+ }
+#endif
+
+ return base;
}
-void WebViewCore::splitContent()
+void WebViewCore::splitContent(PictureSet* content)
{
bool layoutSuceeded = layoutIfNeededRecursive(m_mainFrame);
LOG_ASSERT(layoutSuceeded, "Can never be called recursively");
- PictureSet tempPictureSet;
- m_contentMutex.lock();
- m_content.split(&tempPictureSet);
- m_contentMutex.unlock();
- rebuildPictureSet(&tempPictureSet);
- m_contentMutex.lock();
- m_content.set(tempPictureSet);
- m_contentMutex.unlock();
+ content->split(&m_content);
+ rebuildPictureSet(&m_content);
+ content->set(m_content);
}
void WebViewCore::scrollTo(int x, int y, bool animate)
@@ -936,28 +893,6 @@ void WebViewCore::scrollBy(int dx, int dy, bool animate)
checkException(env);
}
-#if USE(ACCELERATED_COMPOSITING)
-
-void WebViewCore::immediateRepaint()
-{
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- m_javaGlue->m_sendImmediateRepaint);
- checkException(env);
-}
-
-void WebViewCore::setUIRootLayer(const LayerAndroid* layer)
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- m_javaGlue->m_setRootLayer,
- reinterpret_cast<jint>(layer));
- checkException(env);
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
void WebViewCore::contentDraw()
{
JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -1034,24 +969,13 @@ void WebViewCore::updateViewport()
checkException(env);
}
-void WebViewCore::restoreScale(int scale)
+void WebViewCore::restoreScale(int scale, int textWrapScale)
{
DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_restoreScale, scale);
- checkException(env);
-}
-
-void WebViewCore::restoreScreenWidthScale(int scale)
-{
- DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
-
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(),
- m_javaGlue->m_restoreScreenWidthScale, scale);
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_restoreScale, scale, textWrapScale);
checkException(env);
}
@@ -1162,42 +1086,45 @@ void WebViewCore::setGlobalBounds(int x, int y, int h, int v)
}
void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
- int screenWidth, float scale, int realScreenWidth, int screenHeight,
+ int textWrapWidth, float scale, int screenWidth, int screenHeight,
int anchorX, int anchorY, bool ignoreHeight)
{
WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
int ow = window->width();
int oh = window->height();
window->setSize(width, height);
+ window->setVisibleSize(screenWidth, screenHeight);
+ if (width != screenWidth) {
+ m_mainFrame->view()->setUseFixedLayout(true);
+ m_mainFrame->view()->setFixedLayoutSize(IntSize(width, height));
+ } else {
+ m_mainFrame->view()->setUseFixedLayout(false);
+ }
int osw = m_screenWidth;
- int orsw = m_screenWidth * m_screenWidthScale / m_scale;
int osh = m_screenHeight;
+ int otw = m_textWrapWidth;
DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%g) new:(w=%d,h=%d,sw=%d,scale=%g)",
ow, oh, osw, m_scale, width, height, screenWidth, scale);
m_screenWidth = screenWidth;
m_screenHeight = screenHeight;
- if (scale >= 0) { // negative means ignore
+ m_textWrapWidth = textWrapWidth;
+ if (scale >= 0) // negative means keep the current scale
m_scale = scale;
- if (screenWidth != realScreenWidth)
- m_screenWidthScale = realScreenWidth * scale / screenWidth;
- else
- m_screenWidthScale = m_scale;
- }
m_maxXScroll = screenWidth >> 2;
- m_maxYScroll = (screenWidth * height / width) >> 2;
- if (ow != width || (!ignoreHeight && oh != height) || osw != screenWidth) {
+ m_maxYScroll = m_maxXScroll * height / width;
+ if (ow != width || (!ignoreHeight && oh != height) || otw != textWrapWidth) {
WebCore::RenderObject *r = m_mainFrame->contentRenderer();
DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
- realScreenWidth, screenHeight);
+ screenWidth, screenHeight);
if (r) {
WebCore::IntPoint anchorPoint = WebCore::IntPoint(anchorX, anchorY);
DBG_NAV_LOGD("anchorX=%d anchorY=%d", anchorX, anchorY);
- WebCore::Node* node = 0;
+ RefPtr<WebCore::Node> node;
WebCore::IntRect bounds;
WebCore::IntPoint offset;
- // If the screen width changed, it is probably zoom change or
+ // If the text wrap changed, it is probably zoom change or
// orientation change. Try to keep the anchor at the same place.
- if (osw && screenWidth && osw != screenWidth) {
+ if (otw && textWrapWidth && otw != textWrapWidth) {
WebCore::HitTestResult hitTestResult =
m_mainFrame->eventHandler()-> hitTestResultAtPoint(
anchorPoint, false);
@@ -1227,19 +1154,19 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
"h=%d)", newBounds.x(), newBounds.y(),
newBounds.width(), newBounds.height());
- if ((orsw && osh && bounds.width() && bounds.height())
+ if ((osw && osh && bounds.width() && bounds.height())
&& (bounds != newBounds)) {
WebCore::FrameView* view = m_mainFrame->view();
// force left align if width is not changed while height changed.
// the anchorPoint is probably at some white space in the node
// which is affected by text wrap around the screen width.
- const bool leftAlign = (osw != m_screenWidth)
+ const bool leftAlign = (otw != textWrapWidth)
&& (bounds.width() == newBounds.width())
&& (bounds.height() != newBounds.height());
const float xPercentInDoc =
leftAlign ? 0.0 : (float) (anchorX - bounds.x()) / bounds.width();
const float xPercentInView =
- leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / orsw;
+ leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / osw;
const float yPercentInDoc = (float) (anchorY - bounds.y()) / bounds.height();
const float yPercentInView = (float) (anchorY - m_scrollOffsetY) / osh;
showRect(newBounds.x(), newBounds.y(), newBounds.width(),
@@ -1272,7 +1199,7 @@ void WebViewCore::dumpDomTree(bool useFile)
void WebViewCore::dumpRenderTree(bool useFile)
{
#ifdef ANDROID_DOM_LOGGING
- WebCore::CString renderDump = WebCore::externalRepresentation(m_mainFrame).utf8();
+ WTF::CString renderDump = WebCore::externalRepresentation(m_mainFrame).utf8();
const char* data = renderDump.data();
if (useFile) {
gRenderTreeFile = fopen(RENDER_TREE_LOG_FILE, "w");
@@ -1331,7 +1258,7 @@ WebCore::String WebViewCore::requestLabel(WebCore::Frame* frame,
for (unsigned i = 0; i < length; i++) {
WebCore::HTMLLabelElement* label = static_cast<WebCore::HTMLLabelElement*>(
list->item(i));
- if (label->correspondingControl() == node) {
+ if (label->control() == node) {
Node* node = label;
String result;
while ((node = node->traverseNextNode(label))) {
@@ -1437,6 +1364,252 @@ void WebViewCore::updateFrameCacheIfLoading()
updateFrameCache();
}
+struct TouchNodeData {
+ Node* mNode;
+ IntRect mBounds;
+};
+
+// get the bounding box of the Node
+static IntRect getAbsoluteBoundingBox(Node* node) {
+ IntRect rect;
+ RenderObject* render = node->renderer();
+ if (render->isRenderInline())
+ rect = toRenderInline(render)->linesVisibleOverflowBoundingBox();
+ else if (render->isBox())
+ rect = toRenderBox(render)->visualOverflowRect();
+ else if (render->isText())
+ rect = toRenderText(render)->linesBoundingBox();
+ else
+ LOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName());
+ FloatPoint absPos = render->localToAbsolute();
+ rect.move(absPos.x(), absPos.y());
+ return rect;
+}
+
+// get the highlight rectangles for the touch point (x, y) with the slop
+Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
+{
+ Vector<IntRect> rects;
+ m_mousePos = IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
+#ifdef ANDROID_HITTEST_WITHSIZE
+ HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
+ false, false, DontHitTestScrollbars, IntSize(slop, slop));
+ if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
+ LOGE("Should not happen: no in document Node found");
+ return rects;
+ }
+ const Vector<RefPtr<Node> >& list = hitTestResult.rawNodeList();
+ if (list.isEmpty()) {
+ LOGE("Should not happen: no raw node found");
+ return rects;
+ }
+ Frame* frame = hitTestResult.innerNode()->document()->frame();
+ Vector<TouchNodeData> nodeDataList;
+ Vector<RefPtr<Node> >::const_iterator last = list.end();
+ for (Vector<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) {
+ // TODO: it seems reasonable to not search across the frame. Isn't it?
+ // if the node is not in the same frame as the innerNode, skip it
+ if (it->get()->document()->frame() != frame)
+ continue;
+ // traverse up the tree to find the first node that needs highlight
+ bool found = false;
+ Node* eventNode = it->get();
+ while (eventNode) {
+ RenderObject* render = eventNode->renderer();
+ if (render->isBody() || render->isRenderView())
+ break;
+ if (eventNode->supportsFocus()
+ || eventNode->hasEventListeners(eventNames().clickEvent)
+ || eventNode->hasEventListeners(eventNames().mousedownEvent)
+ || eventNode->hasEventListeners(eventNames().mouseupEvent)) {
+ found = true;
+ break;
+ }
+ // the nodes in the rawNodeList() are ordered based on z-index during hit testing.
+ // so do not search for the eventNode across explicit z-index border.
+ // TODO: this is a hard one to call. z-index is quite complicated as its value only
+ // matters when you compare two RenderLayer in the same hierarchy level. e.g. in
+ // the following example, "b" is on the top as its z level is the highest. even "c"
+ // has 100 as z-index, it is still below "d" as its parent has the same z-index as
+ // "d" and logically before "d". Of course "a" is the lowest in the z level.
+ //
+ // z-index:auto "a"
+ // z-index:2 "b"
+ // z-index:1
+ // z-index:100 "c"
+ // z-index:1 "d"
+ //
+ // If the fat point touches everyone, the order in the list should be "b", "d", "c"
+ // and "a". When we search for the event node for "b", we really don't want "a" as
+ // in the z-order it is behind everything else.
+ if (!render->style()->hasAutoZIndex())
+ break;
+ eventNode = eventNode->parentNode();
+ }
+ // didn't find any eventNode, skip it
+ if (!found)
+ continue;
+ // first quick check whether it is a duplicated node before computing bounding box
+ Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
+ for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
+ // found the same node, skip it
+ if (eventNode == n->mNode) {
+ found = false;
+ break;
+ }
+ }
+ if (!found)
+ continue;
+ // next check whether the node is fully covered by or fully covering another node.
+ found = false;
+ IntRect rect = getAbsoluteBoundingBox(eventNode);
+ if (rect.isEmpty()) {
+ // if the node's bounds is empty and it is not a ContainerNode, skip it.
+ if (!eventNode->isContainerNode())
+ continue;
+ // if the node's children are all positioned objects, its bounds can be empty.
+ // Walk through the children to find the bounding box.
+ Node* child = static_cast<const ContainerNode*>(eventNode)->firstChild();
+ while (child) {
+ IntRect childrect;
+ if (child->renderer())
+ childrect = getAbsoluteBoundingBox(child);
+ if (!childrect.isEmpty()) {
+ rect.unite(childrect);
+ child = child->traverseNextSibling(eventNode);
+ } else
+ child = child->traverseNextNode(eventNode);
+ }
+ }
+ for (int i = nodeDataList.size() - 1; i >= 0; i--) {
+ TouchNodeData n = nodeDataList.at(i);
+ // the new node is enclosing an existing node, skip it
+ if (rect.contains(n.mBounds)) {
+ found = true;
+ break;
+ }
+ // the new node is fully inside an existing node, remove the existing node
+ if (n.mBounds.contains(rect))
+ nodeDataList.remove(i);
+ }
+ if (!found) {
+ TouchNodeData newNode;
+ newNode.mNode = eventNode;
+ newNode.mBounds = rect;
+ nodeDataList.append(newNode);
+ }
+ }
+ if (!nodeDataList.size())
+ return rects;
+ // finally select the node with the largest overlap with the fat point
+ TouchNodeData final;
+ final.mNode = 0;
+ IntPoint docPos = frame->view()->windowToContents(m_mousePos);
+ IntRect testRect(docPos.x() - slop, docPos.y() - slop, 2 * slop + 1, 2 * slop + 1);
+ int area = 0;
+ Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
+ for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
+ IntRect rect = n->mBounds;
+ rect.intersect(testRect);
+ int a = rect.width() * rect.height();
+ if (a > area) {
+ final = *n;
+ area = a;
+ }
+ }
+ // now get the node's highlight rectangles in the page coordinate system
+ if (final.mNode) {
+ IntPoint frameAdjust;
+ if (frame != m_mainFrame) {
+ frameAdjust = frame->view()->contentsToWindow(IntPoint());
+ frameAdjust.move(m_scrollOffsetX, m_scrollOffsetY);
+ }
+ if (final.mNode->isLink()) {
+ // most of the links are inline instead of box style. So the bounding box is not
+ // a good representation for the highlights. Get the list of rectangles instead.
+ RenderObject* render = final.mNode->renderer();
+ IntPoint offset = roundedIntPoint(render->localToAbsolute());
+ render->absoluteRects(rects, offset.x() + frameAdjust.x(), offset.y() + frameAdjust.y());
+ bool inside = false;
+ int distance = INT_MAX;
+ int newx = x, newy = y;
+ int i = rects.size();
+ while (i--) {
+ if (rects[i].isEmpty()) {
+ rects.remove(i);
+ continue;
+ }
+ // check whether the point (x, y) is inside one of the rectangles.
+ if (inside)
+ continue;
+ if (rects[i].contains(x, y)) {
+ inside = true;
+ continue;
+ }
+ if (x >= rects[i].x() && x < rects[i].right()) {
+ if (y < rects[i].y()) {
+ if (rects[i].y() - y < distance) {
+ newx = x;
+ newy = rects[i].y();
+ distance = rects[i].y() - y;
+ }
+ } else if (y >= rects[i].bottom()) {
+ if (y - rects[i].bottom() + 1 < distance) {
+ newx = x;
+ newy = rects[i].bottom() - 1;
+ distance = y - rects[i].bottom() + 1;
+ }
+ }
+ } else if (y >= rects[i].y() && y < rects[i].bottom()) {
+ if (x < rects[i].x()) {
+ if (rects[i].x() - x < distance) {
+ newx = rects[i].x();
+ newy = y;
+ distance = rects[i].x() - x;
+ }
+ } else if (x >= rects[i].right()) {
+ if (x - rects[i].right() + 1 < distance) {
+ newx = rects[i].right() - 1;
+ newy = y;
+ distance = x - rects[i].right() + 1;
+ }
+ }
+ }
+ }
+ if (!rects.isEmpty()) {
+ if (!inside) {
+ // if neither x nor y has overlap, just pick the top/left of the first rectangle
+ if (newx == x && newy == y) {
+ newx = rects[0].x();
+ newy = rects[0].y();
+ }
+ m_mousePos.setX(newx - m_scrollOffsetX);
+ m_mousePos.setY(newy - m_scrollOffsetY);
+ DBG_NAV_LOGD("Move x/y from (%d, %d) to (%d, %d) scrollOffset is (%d, %d)",
+ x, y, m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY,
+ m_scrollOffsetX, m_scrollOffsetY);
+ }
+ return rects;
+ }
+ }
+ IntRect rect = final.mBounds;
+ rect.move(frameAdjust.x(), frameAdjust.y());
+ rects.append(rect);
+ // adjust m_mousePos if it is not inside the returned highlight rectangle
+ testRect.move(frameAdjust.x(), frameAdjust.y());
+ testRect.intersect(rect);
+ if (!testRect.contains(x, y)) {
+ m_mousePos = testRect.center();
+ m_mousePos.move(-m_scrollOffsetX, -m_scrollOffsetY);
+ DBG_NAV_LOGD("Move x/y from (%d, %d) to (%d, %d) scrollOffset is (%d, %d)",
+ x, y, m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY,
+ m_scrollOffsetX, m_scrollOffsetY);
+ }
+ }
+#endif
+ return rects;
+}
+
///////////////////////////////////////////////////////////////////////////////
void WebViewCore::addPlugin(PluginWidgetAndroid* w)
@@ -1675,6 +1848,51 @@ void WebViewCore::setSelection(int start, int end)
setFocusControllerActive(focusedFrame, true);
}
+String WebViewCore::modifySelection(const String& alter, const String& direction, const String& granularity)
+{
+ DOMSelection* selection = m_mainFrame->domWindow()->getSelection();
+
+ if (selection->rangeCount() == 0) {
+ Document* document = m_mainFrame->document();
+ HTMLElement* body = document->body();
+ ExceptionCode ec;
+
+ PassRefPtr<Range> rangeRef = document->createRange();
+ rangeRef->setStart(PassRefPtr<Node>(body), 0, ec);
+ if (ec) {
+ LOGE("Error setting range start. Error code: %d", ec);
+ return String();
+ }
+
+ rangeRef->setEnd(PassRefPtr<Node>(body), 0, ec);
+ if (ec) {
+ LOGE("Error setting range end. Error code: %d", ec);
+ return String();
+ }
+
+ selection->addRange(rangeRef.get());
+ }
+
+ if (equalIgnoringCase(direction, "forward")) {
+ selection->collapseToEnd();
+ } else if (equalIgnoringCase(direction, "backward")) {
+ selection->collapseToStart();
+ } else {
+ LOGE("Invalid direction: %s", direction.utf8().data());
+ return String();
+ }
+
+ // NOTE: The selection of WebKit misbehaves and I need to add some
+ // voodoo here to force it behave well. Rachel did something similar
+ // in JS and I want to make sure it is optimal before adding it here.
+
+ selection->modify(alter, direction, granularity);
+ String selection_string = selection->toString();
+ LOGD("Selection string: %s", selection_string.utf8().data());
+
+ return selection_string;
+}
+
void WebViewCore::deleteSelection(int start, int end, int textGeneration)
{
setSelection(start, end);
@@ -1918,15 +2136,24 @@ void WebViewCore::openFileChooser(PassRefPtr<WebCore::FileChooser> chooser) {
if (!chooser)
return;
JNIEnv* env = JSC::Bindings::getJNIEnv();
+
+ WebCore::String acceptType = chooser->acceptTypes();
+ jstring jAcceptType = env->NewString(const_cast<unsigned short*>(acceptType.characters()), acceptType.length());
jstring jName = (jstring) env->CallObjectMethod(
- m_javaGlue->object(env).get(), m_javaGlue->m_openFileChooser);
+ m_javaGlue->object(env).get(), m_javaGlue->m_openFileChooser, jAcceptType);
checkException(env);
- const UChar* string = (const UChar*) env->GetStringChars(jName, NULL);
+ env->DeleteLocalRef(jAcceptType);
+
+ const UChar* string = static_cast<const UChar*>(env->GetStringChars(jName, NULL));
+
if (!string)
return;
+
WebCore::String webcoreString = to_string(env, jName);
env->ReleaseStringChars(jName, string);
- chooser->chooseFile(webcoreString);
+
+ if (webcoreString.length())
+ chooser->chooseFile(webcoreString);
}
void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount,
@@ -1985,12 +2212,25 @@ void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, s
bool WebViewCore::key(const PlatformKeyboardEvent& event)
{
- WebCore::EventHandler* eventHandler = m_mainFrame->eventHandler();
+ WebCore::EventHandler* eventHandler;
WebCore::Node* focusNode = currentFocus();
- if (focusNode)
- eventHandler = focusNode->document()->frame()->eventHandler();
DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p",
event.keyIdentifier().utf8().data(), event.unichar(), focusNode);
+ if (focusNode) {
+ WebCore::Frame* frame = focusNode->document()->frame();
+ eventHandler = frame->eventHandler();
+ if (focusNode->isContentEditable()) {
+ // keyEvent will return true even if the contentEditable did not
+ // change its selection. In the case that it does not, we want to
+ // return false so that the key will be sent back to our navigation
+ // system.
+ VisibleSelection old = frame->selection()->selection();
+ eventHandler->keyEvent(event);
+ return frame->selection()->selection() != old;
+ }
+ } else {
+ eventHandler = m_mainFrame->eventHandler();
+ }
return eventHandler->keyEvent(event);
}
@@ -2075,14 +2315,6 @@ bool WebViewCore::handleTouchEvent(int action, int x, int y, int metaState)
// Track previous touch and if stationary set the state.
WebCore::IntPoint pt(x - m_scrollOffsetX, y - m_scrollOffsetY);
-// handleTouchEvent() in EventHandler.cpp doesn't handle TouchStationary, which
-// causes preventDefault be false when it returns. As our Java side may continue
-// process the events if WebKit doesn't, it can cause unexpected result.
-// if (type == WebCore::TouchMove && pt == m_lastTouchPoint)
-// touchState = WebCore::PlatformTouchPoint::TouchStationary;
-
- m_lastTouchPoint = pt;
-
WebCore::PlatformTouchEvent te(pt, type, touchState, metaState);
preventDefault = m_mainFrame->eventHandler()->handleTouchEvent(te);
#endif
@@ -2097,6 +2329,16 @@ bool WebViewCore::handleTouchEvent(int action, int x, int y, int metaState)
void WebViewCore::touchUp(int touchGeneration,
WebCore::Frame* frame, WebCore::Node* node, int x, int y)
{
+ if (touchGeneration == 0) {
+ // m_mousePos should be set in getTouchHighlightRects()
+ WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(m_mousePos, false);
+ node = hitTestResult.innerNode();
+ if (node)
+ frame = node->document()->frame();
+ else
+ frame = 0;
+ DBG_NAV_LOGD("touch up on (%d, %d), scrollOffset is (%d, %d), node:%p, frame:%p", m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY, m_scrollOffsetX, m_scrollOffsetY, node, frame);
+ } else {
if (m_touchGeneration > touchGeneration) {
DBG_NAV_LOGD("m_touchGeneration=%d > touchGeneration=%d"
" x=%d y=%d", m_touchGeneration, touchGeneration, x, y);
@@ -2106,6 +2348,7 @@ void WebViewCore::touchUp(int touchGeneration,
// m_mousePos to determine where the click happens.
moveMouse(frame, x, y);
m_lastGeneration = touchGeneration;
+ }
if (frame && CacheBuilder::validNode(m_mainFrame, frame, 0)) {
frame->loader()->resetMultipleFormSubmissionProtection();
}
@@ -2203,6 +2446,9 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
} else {
requestKeyboard(false);
}
+ } else if (focusNode->isContentEditable()) {
+ setFocusControllerActive(framePtr, true);
+ requestKeyboard(true);
}
}
return handled;
@@ -2542,6 +2788,13 @@ void WebViewCore::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode
checkException(env);
}
+void WebViewCore::notifyWebAppCanBeInstalled()
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_setInstallableWebApp);
+ checkException(env);
+}
+
//----------------------------------------------------------------------
// Native JNI methods
//----------------------------------------------------------------------
@@ -2568,7 +2821,7 @@ static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj)
}
static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
- jint screenWidth, jfloat scale, jint realScreenWidth, jint screenHeight,
+ jint textWrapWidth, jfloat scale, jint screenWidth, jint screenHeight,
jint anchorX, jint anchorY, jboolean ignoreHeight)
{
#ifdef ANDROID_INSTRUMENT
@@ -2577,8 +2830,8 @@ static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
LOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl);
LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize");
- viewImpl->setSizeScreenWidthAndScale(width, height, screenWidth, scale,
- realScreenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
+ viewImpl->setSizeScreenWidthAndScale(width, height, textWrapWidth, scale,
+ screenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
}
static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint x, jint y)
@@ -2646,6 +2899,22 @@ static void SetSelection(JNIEnv *env, jobject obj, jint start, jint end)
viewImpl->setSelection(start, end);
}
+static jstring ModifySelection(JNIEnv *env, jobject obj, jstring alter, jstring direction, jstring granularity)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+ String alterString = to_string(env, alter);
+ String directionString = to_string(env, direction);
+ String granularityString = to_string(env, granularity);
+
+ WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ String selection_string = viewImpl->modifySelection(alterString,
+ directionString,
+ granularityString);
+
+ return WebCoreStringToJString(env, selection_string);
+}
static void ReplaceTextfieldText(JNIEnv *env, jobject obj,
jint oldStart, jint oldEnd, jstring replace, jint start, jint end,
@@ -2710,7 +2979,7 @@ void WebViewCore::addVisitedLink(const UChar* string, int length)
m_groupForVisitedLinks->addVisitedLink(string, length);
}
-static bool RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
+static jint RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
@@ -2718,18 +2987,18 @@ static bool RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
SkRegion* nativeRegion = GraphicsJNI::getNativeRegion(env, region);
SkIPoint nativePt;
- bool result = viewImpl->recordContent(nativeRegion, &nativePt);
+ BaseLayerAndroid* result = viewImpl->recordContent(nativeRegion, &nativePt);
GraphicsJNI::ipoint_to_jpoint(nativePt, env, pt);
- return result;
+ return reinterpret_cast<jint>(result);
}
-static void SplitContent(JNIEnv *env, jobject obj)
+static void SplitContent(JNIEnv *env, jobject obj, jint content)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
#endif
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- viewImpl->splitContent();
+ viewImpl->splitContent(reinterpret_cast<PictureSet*>(content));
}
static void SendListBoxChoice(JNIEnv* env, jobject obj, jint choice)
@@ -2981,7 +3250,7 @@ static void SetJsFlags(JNIEnv *env, jobject obj, jstring flags)
{
#if USE(V8)
WebCore::String flagsString = to_string(env, flags);
- WebCore::CString utf8String = flagsString.utf8();
+ WTF::CString utf8String = flagsString.utf8();
WebCore::ScriptController::setFlags(utf8String.data(), utf8String.length());
#endif
}
@@ -3018,45 +3287,11 @@ static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jstring scheme) {
WebCore::SecurityOrigin::registerURLSchemeAsLocal(to_string(env, scheme));
}
-static void ClearContent(JNIEnv *env, jobject obj)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- viewImpl->clearContent();
-}
-
-static void CopyContentToPicture(JNIEnv *env, jobject obj, jobject pict)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- if (!viewImpl)
- return;
- SkPicture* picture = GraphicsJNI::getNativePicture(env, pict);
- viewImpl->copyContentToPicture(picture);
-}
-
-static bool DrawContent(JNIEnv *env, jobject obj, jobject canv, jint color)
-{
- // Note: this is called from UI thread, don't count it for WebViewCoreTimeCounter
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
- return viewImpl->drawContent(canvas, color);
-}
-
static bool FocusBoundsChanged(JNIEnv* env, jobject obj)
{
return GET_NATIVE_VIEW(env, obj)->focusBoundsChanged();
}
-static bool PictureReady(JNIEnv* env, jobject obj)
-{
- return GET_NATIVE_VIEW(env, obj)->pictureReady();
-}
-
static void Pause(JNIEnv* env, jobject obj)
{
// This is called for the foreground tab when the browser is put to the
@@ -3151,26 +3386,54 @@ static bool ValidNodeAndBounds(JNIEnv *env, jobject obj, int frame, int node,
reinterpret_cast<Node*>(node), nativeRect);
}
+static jobject GetTouchHighlightRects(JNIEnv* env, jobject obj, jint x, jint y, jint slop)
+{
+ WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ if (!viewImpl)
+ return NULL;
+ Vector<IntRect> rects = viewImpl->getTouchHighlightRects(x, y, slop);
+ if (rects.isEmpty())
+ return NULL;
+
+ jclass arrayClass = env->FindClass("java/util/ArrayList");
+ LOG_ASSERT(arrayClass, "Could not find java/util/ArrayList");
+ jmethodID init = env->GetMethodID(arrayClass, "<init>", "(I)V");
+ LOG_ASSERT(init, "Could not find constructor for ArrayList");
+ jobject array = env->NewObject(arrayClass, init, rects.size());
+ LOG_ASSERT(vector, "Could not create a new ArrayList");
+ jmethodID add = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");
+ LOG_ASSERT(add, "Could not find add method on ArrayList");
+ jclass rectClass = env->FindClass("android/graphics/Rect");
+ LOG_ASSERT(rectClass, "Could not find android/graphics/Rect");
+ jmethodID rectinit = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+ LOG_ASSERT(rectinit, "Could not find init method on Rect");
+
+ for (size_t i = 0; i < rects.size(); i++) {
+ jobject rect = env->NewObject(rectClass, rectinit, rects[i].x(),
+ rects[i].y(), rects[i].right(), rects[i].bottom());
+ if (rect) {
+ env->CallBooleanMethod(array, add, rect);
+ env->DeleteLocalRef(rect);
+ }
+ }
+
+ env->DeleteLocalRef(rectClass);
+ env->DeleteLocalRef(arrayClass);
+ return array;
+}
+
// ----------------------------------------------------------------------------
/*
* JNI registration.
*/
static JNINativeMethod gJavaWebViewCoreMethods[] = {
- { "nativeClearContent", "()V",
- (void*) ClearContent },
- { "nativeCopyContentToPicture", "(Landroid/graphics/Picture;)V",
- (void*) CopyContentToPicture },
- { "nativeDrawContent", "(Landroid/graphics/Canvas;I)Z",
- (void*) DrawContent } ,
{ "nativeFocusBoundsChanged", "()Z",
(void*) FocusBoundsChanged } ,
{ "nativeKey", "(IIIZZZZ)Z",
(void*) Key },
{ "nativeClick", "(II)V",
(void*) Click },
- { "nativePictureReady", "()Z",
- (void*) PictureReady } ,
{ "nativeSendListBoxChoices", "([ZI)V",
(void*) SendListBoxChoices },
{ "nativeSendListBoxChoice", "(I)V",
@@ -3183,6 +3446,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) SetGlobalBounds },
{ "nativeSetSelection", "(II)V",
(void*) SetSelection } ,
+ { "nativeModifySelection", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+ (void*) ModifySelection },
{ "nativeDeleteSelection", "(III)V",
(void*) DeleteSelection } ,
{ "nativeReplaceTextfieldText", "(IILjava/lang/String;III)V",
@@ -3215,11 +3480,11 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) UpdateFrameCache },
{ "nativeGetContentMinPrefWidth", "()I",
(void*) GetContentMinPrefWidth },
- { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)Z",
+ { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)I",
(void*) RecordContent },
{ "setViewportSettingsFromNative", "()V",
(void*) SetViewportSettingsFromNative },
- { "nativeSplitContent", "()V",
+ { "nativeSplitContent", "(I)V",
(void*) SplitContent },
{ "nativeSetBackgroundColor", "(I)V",
(void*) SetBackgroundColor },
@@ -3251,6 +3516,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) FullScreenPluginHidden },
{ "nativeValidNodeAndBounds", "(IILandroid/graphics/Rect;)Z",
(void*) ValidNodeAndBounds },
+ { "nativeGetTouchHighlightRects", "(III)Ljava/util/ArrayList;",
+ (void*) GetTouchHighlightRects },
};
int register_webviewcore(JNIEnv* env)