summaryrefslogtreecommitdiffstats
path: root/Source/WebKit/android/jni/WebViewCore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit/android/jni/WebViewCore.cpp')
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp3303
1 files changed, 1826 insertions, 1477 deletions
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index 1b53a6e..f17e573 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -29,10 +29,9 @@
#include "WebViewCore.h"
#include "AccessibilityObject.h"
+#include "AndroidHitTestResult.h"
#include "Attribute.h"
-#include "BaseLayerAndroid.h"
-#include "CachedNode.h"
-#include "CachedRoot.h"
+#include "content/address_detector.h"
#include "Chrome.h"
#include "ChromeClientAndroid.h"
#include "ChromiumIncludes.h"
@@ -43,6 +42,7 @@
#include "CSSValueKeywords.h"
#include "DatabaseTracker.h"
#include "Document.h"
+#include "DocumentMarkerController.h"
#include "DOMWindow.h"
#include "DOMSelection.h"
#include "Element.h"
@@ -53,6 +53,7 @@
#include "ExceptionCode.h"
#include "FocusController.h"
#include "Font.h"
+#include "FontCache.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClientAndroid.h"
@@ -61,6 +62,7 @@
#include "Geolocation.h"
#include "GraphicsContext.h"
#include "GraphicsJNI.h"
+#include "GraphicsOperationCollection.h"
#include "HTMLAnchorElement.h"
#include "HTMLAreaElement.h"
#include "HTMLElement.h"
@@ -78,6 +80,7 @@
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "InlineTextBox.h"
+#include "KeyboardEvent.h"
#include "MemoryUsage.h"
#include "NamedNodeMap.h"
#include "Navigator.h"
@@ -85,6 +88,8 @@
#include "NodeList.h"
#include "Page.h"
#include "PageGroup.h"
+#include "PictureLayerContent.h"
+#include "PicturePileLayerContent.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformString.h"
#include "PluginWidgetAndroid.h"
@@ -93,6 +98,7 @@
#include "ProgressTracker.h"
#include "Range.h"
#include "RenderBox.h"
+#include "RenderImage.h"
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderPart.h"
@@ -103,38 +109,43 @@
#include "ResourceRequest.h"
#include "RuntimeEnabledFeatures.h"
#include "SchemeRegistry.h"
+#include "ScopedLocalRef.h"
+#include "ScriptController.h"
#include "SelectionController.h"
+#include "SelectText.h"
#include "Settings.h"
#include "SkANP.h"
#include "SkTemplates.h"
#include "SkTDArray.h"
#include "SkTypes.h"
#include "SkCanvas.h"
+#include "SkGraphics.h"
#include "SkPicture.h"
#include "SkUtils.h"
#include "Text.h"
+#include "TextIterator.h"
+#include "TilesManager.h"
#include "TypingCommand.h"
#include "WebCache.h"
#include "WebCoreFrameBridge.h"
+#include "WebCoreJni.h"
#include "WebFrameView.h"
#include "WindowsKeyboardCodes.h"
#include "android_graphics.h"
#include "autofill/WebAutofill.h"
#include "htmlediting.h"
#include "markup.h"
+#include "visible_units.h"
#include <JNIHelp.h>
#include <JNIUtility.h>
-#include <ui/KeycodeLabels.h>
+#include <androidfw/KeycodeLabels.h>
+#include <cutils/properties.h>
+#include <v8.h>
#include <wtf/CurrentTime.h>
#include <wtf/text/AtomicString.h>
-#include <wtf/text/StringImpl.h>
-
-#if USE(V8)
-#include "ScriptController.h"
-#include "V8Counters.h"
#include <wtf/text/CString.h>
-#endif
+#include <wtf/text/StringImpl.h>
#if DEBUG_NAV_UI
#include "SkTime.h"
@@ -153,34 +164,85 @@ FILE* gDomTreeFile = 0;
FILE* gRenderTreeFile = 0;
#endif
-#ifdef ANDROID_INSTRUMENT
-#include "TimeCounter.h"
-#endif
+#include "BaseLayerAndroid.h"
#if USE(ACCELERATED_COMPOSITING)
#include "GraphicsLayerAndroid.h"
#include "RenderLayerCompositor.h"
#endif
-#if USE(V8)
-#include <v8.h>
-#endif
+#define FOREGROUND_TIMER_INTERVAL 0.004 // 4ms
+#define BACKGROUND_TIMER_INTERVAL 1.0 // 1s
-// In some cases, too many invalidations passed to the UI will slow us down.
-// Limit ourselves to 32 rectangles, past this just send the area bounds to the UI.
-// see WebViewCore::recordPictureSet().
-#define MAX_INVALIDATIONS 32
+// How many ms to wait for the scroll to "settle" before we will consider doing
+// prerenders
+#define PRERENDER_AFTER_SCROLL_DELAY 750
-/* We pass this flag when recording the actual content, so that we don't spend
- time actually regionizing complex path clips, when all we really want to do
- is record them.
- */
-#define PICT_RECORD_FLAGS SkPicture::kUsePathBoundsForClip_RecordingFlag
+#define TOUCH_FLAG_HIT_HANDLER 0x1
+#define TOUCH_FLAG_PREVENT_DEFAULT 0x2
////////////////////////////////////////////////////////////////////////////////////////////////
namespace android {
+// Copied from CacheBuilder, not sure if this is needed/correct
+IntRect getAreaRect(const HTMLAreaElement* area)
+{
+ Node* node = area->document();
+ while ((node = node->traverseNextNode()) != NULL) {
+ RenderObject* renderer = node->renderer();
+ if (renderer && renderer->isRenderImage()) {
+ RenderImage* image = static_cast<RenderImage*>(renderer);
+ HTMLMapElement* map = image->imageMap();
+ if (map) {
+ Node* n;
+ for (n = map->firstChild(); n;
+ n = n->traverseNextNode(map)) {
+ if (n == area) {
+ if (area->isDefault())
+ return image->absoluteBoundingBoxRect();
+ return area->computeRect(image);
+ }
+ }
+ }
+ }
+ }
+ return IntRect();
+}
+
+// Copied from CacheBuilder, not sure if this is needed/correct
+// TODO: See if this is even needed (I suspect not), and if not remove it
+bool validNode(Frame* startFrame, void* matchFrame,
+ void* matchNode)
+{
+ if (matchFrame == startFrame) {
+ if (matchNode == NULL)
+ return true;
+ Node* node = startFrame->document();
+ while (node != NULL) {
+ if (node == matchNode) {
+ const IntRect& rect = node->hasTagName(HTMLNames::areaTag) ?
+ getAreaRect(static_cast<HTMLAreaElement*>(node)) : node->getRect();
+ // Consider nodes with empty rects that are not at the origin
+ // to be valid, since news.google.com has valid nodes like this
+ if (rect.x() == 0 && rect.y() == 0 && rect.isEmpty())
+ return false;
+ return true;
+ }
+ node = node->traverseNextNode();
+ }
+ return false;
+ }
+ Frame* child = startFrame->tree()->firstChild();
+ while (child) {
+ bool result = validNode(child, matchFrame, matchNode);
+ if (result)
+ return result;
+ child = child->tree()->nextSibling();
+ }
+ return false;
+}
+
static SkTDArray<WebViewCore*> gInstanceList;
void WebViewCore::addInstance(WebViewCore* inst) {
@@ -189,7 +251,7 @@ void WebViewCore::addInstance(WebViewCore* inst) {
void WebViewCore::removeInstance(WebViewCore* inst) {
int index = gInstanceList.find(inst);
- LOG_ASSERT(index >= 0, "RemoveInstance inst not found");
+ ALOG_ASSERT(index >= 0, "RemoveInstance inst not found");
if (index >= 0) {
gInstanceList.removeShuffle(index);
}
@@ -242,8 +304,6 @@ bool WebViewCore::isSupportedMediaMimeType(const WTF::String& mimeType) {
// ----------------------------------------------------------------------------
-#define GET_NATIVE_VIEW(env, obj) ((WebViewCore*)env->GetIntField(obj, gWebViewCoreFields.m_nativeClass))
-
// Field ids for WebViewCore
struct WebViewCoreFields {
jfieldID m_nativeClass;
@@ -254,7 +314,6 @@ struct WebViewCoreFields {
jfieldID m_viewportMaximumScale;
jfieldID m_viewportUserScalable;
jfieldID m_viewportDensityDpi;
- jfieldID m_webView;
jfieldID m_drawIsPaused;
jfieldID m_lowMemoryUsageMb;
jfieldID m_highMemoryUsageMb;
@@ -267,7 +326,6 @@ struct WebViewCore::JavaGlue {
jweak m_obj;
jmethodID m_scrollTo;
jmethodID m_contentDraw;
- jmethodID m_layersDraw;
jmethodID m_requestListBox;
jmethodID m_openFileChooser;
jmethodID m_requestSingleListBox;
@@ -276,17 +334,18 @@ struct WebViewCore::JavaGlue {
jmethodID m_jsPrompt;
jmethodID m_jsUnload;
jmethodID m_jsInterrupt;
+ jmethodID m_getWebView;
jmethodID m_didFirstLayout;
jmethodID m_updateViewport;
jmethodID m_sendNotifyProgressFinished;
jmethodID m_sendViewInvalidate;
jmethodID m_updateTextfield;
jmethodID m_updateTextSelection;
+ jmethodID m_updateTextSizeAndScroll;
jmethodID m_clearTextEntry;
jmethodID m_restoreScale;
jmethodID m_needTouchEvents;
jmethodID m_requestKeyboard;
- jmethodID m_requestKeyboardWithSelection;
jmethodID m_exceededDatabaseQuota;
jmethodID m_reachedMaxAppCacheSize;
jmethodID m_populateVisitedLinks;
@@ -295,7 +354,7 @@ struct WebViewCore::JavaGlue {
jmethodID m_getDeviceMotionService;
jmethodID m_getDeviceOrientationService;
jmethodID m_addMessageToConsole;
- jmethodID m_formDidBlur;
+ jmethodID m_focusNodeChanged;
jmethodID m_getPluginClass;
jmethodID m_showFullScreenPlugin;
jmethodID m_hideFullScreenPlugin;
@@ -305,14 +364,17 @@ struct WebViewCore::JavaGlue {
jmethodID m_destroySurface;
jmethodID m_getContext;
jmethodID m_keepScreenOn;
- jmethodID m_sendFindAgain;
jmethodID m_showRect;
jmethodID m_centerFitRect;
jmethodID m_setScrollbarModes;
jmethodID m_setInstallableWebApp;
jmethodID m_enterFullscreenForVideoLayer;
+ jmethodID m_exitFullscreenVideo;
jmethodID m_setWebTextViewAutoFillable;
jmethodID m_selectAt;
+ jmethodID m_initEditField;
+ jmethodID m_chromeCanTakeFocus;
+ jmethodID m_chromeTakeFocus;
AutoJObject object(JNIEnv* env) {
// We hold a weak reference to the Java WebViewCore to avoid memeory
// leaks due to circular references when WebView.destroy() is not
@@ -325,6 +387,23 @@ struct WebViewCore::JavaGlue {
}
};
+struct WebViewCore::TextFieldInitDataGlue {
+ jmethodID m_constructor;
+ jfieldID m_fieldPointer;
+ jfieldID m_text;
+ jfieldID m_type;
+ jfieldID m_isSpellCheckEnabled;
+ jfieldID m_isTextFieldNext;
+ jfieldID m_isTextFieldPrev;
+ jfieldID m_isAutoCompleteEnabled;
+ jfieldID m_name;
+ jfieldID m_label;
+ jfieldID m_maxLength;
+ jfieldID m_contentBounds;
+ jfieldID m_nodeLayerId;
+ jfieldID m_contentRect;
+};
+
/*
* WebViewCore Implementation
*/
@@ -332,58 +411,37 @@ struct WebViewCore::JavaGlue {
static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
{
jmethodID m = env->GetMethodID(clazz, name, signature);
- LOG_ASSERT(m, "Could not find method %s", name);
+ ALOG_ASSERT(m, "Could not find method %s", name);
return m;
}
-Mutex WebViewCore::gFrameCacheMutex;
-Mutex WebViewCore::gCursorBoundsMutex;
-
WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* mainframe)
- : m_frameCacheKit(0)
- , m_navPictureKit(0)
- , m_moveGeneration(0)
- , m_touchGeneration(0)
+ : m_touchGeneration(0)
, m_lastGeneration(0)
- , m_updatedFrameCache(true)
- , m_findIsUp(false)
- , m_hasCursorBounds(false)
- , m_cursorBounds(WebCore::IntRect(0, 0, 0, 0))
- , m_cursorHitBounds(WebCore::IntRect(0, 0, 0, 0))
- , m_cursorFrame(0)
- , m_cursorLocation(WebCore::IntPoint(0, 0))
- , m_cursorNode(0)
, m_javaGlue(new JavaGlue)
+ , m_textFieldInitDataGlue(new TextFieldInitDataGlue)
, m_mainFrame(mainframe)
, m_popupReply(0)
- , m_lastFocused(0)
- , m_lastFocusedBounds(WebCore::IntRect(0,0,0,0))
- , m_blurringNodePointer(0)
- , m_lastFocusedSelStart(0)
- , m_lastFocusedSelEnd(0)
, m_blockTextfieldUpdates(false)
, m_focusBoundsChanged(false)
, m_skipContentDraw(false)
, m_textGeneration(0)
- , m_temp(0)
- , m_tempPict(0)
, m_maxXScroll(320/4)
, m_maxYScroll(240/4)
, m_scrollOffsetX(0)
, m_scrollOffsetY(0)
, m_mousePos(WebCore::IntPoint(0,0))
- , m_frameCacheOutOfDate(true)
- , m_progressDone(false)
, m_screenWidth(320)
, m_screenHeight(240)
, m_textWrapWidth(320)
, m_scale(1.0f)
- , m_domtree_version(0)
- , m_check_domtree_version(true)
, m_groupForVisitedLinks(0)
, m_isPaused(false)
, m_cacheMode(0)
- , m_shouldPaintCaret(true)
+ , m_fullscreenVideoMode(false)
+ , m_matchCount(0)
+ , m_activeMatchIndex(0)
+ , m_activeMatch(0)
, m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
, m_screenOnCounter(0)
, m_currentNodeDomNavigationAxis(0)
@@ -391,36 +449,35 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
#if ENABLE(TOUCH_EVENTS)
, m_forwardingTouchEvents(false)
#endif
-#if USE(CHROME_NETWORK_STACK)
, m_webRequestContext(0)
-#endif
+ , m_prerenderEnabled(false)
{
- LOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
+ ALOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
jclass clazz = env->GetObjectClass(javaWebViewCore);
m_javaGlue->m_obj = env->NewWeakGlobalRef(javaWebViewCore);
m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(IIZZ)V");
m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V");
- m_javaGlue->m_layersDraw = GetJMethod(env, clazz, "layersDraw", "()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;)Ljava/lang/String;");
+ m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "(Ljava/lang/String;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");
m_javaGlue->m_jsPrompt = GetJMethod(env, clazz, "jsPrompt", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
m_javaGlue->m_jsUnload = GetJMethod(env, clazz, "jsUnload", "(Ljava/lang/String;Ljava/lang/String;)Z");
m_javaGlue->m_jsInterrupt = GetJMethod(env, clazz, "jsInterrupt", "()Z");
+ m_javaGlue->m_getWebView = GetJMethod(env, clazz, "getWebView", "()Landroid/webkit/WebView;");
m_javaGlue->m_didFirstLayout = GetJMethod(env, clazz, "didFirstLayout", "(Z)V");
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_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
- m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V");
+ m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIIII)V");
+ m_javaGlue->m_updateTextSizeAndScroll = GetJMethod(env, clazz, "updateTextSizeAndScroll", "(IIIII)V");
m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
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");
@@ -429,7 +486,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_getDeviceMotionService = GetJMethod(env, clazz, "getDeviceMotionService", "()Landroid/webkit/DeviceMotionService;");
m_javaGlue->m_getDeviceOrientationService = GetJMethod(env, clazz, "getDeviceOrientationService", "()Landroid/webkit/DeviceOrientationService;");
m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;I)V");
- m_javaGlue->m_formDidBlur = GetJMethod(env, clazz, "formDidBlur", "(I)V");
+ m_javaGlue->m_focusNodeChanged = GetJMethod(env, clazz, "focusNodeChanged", "(ILandroid/webkit/WebViewCore$WebKitHitTest;)V");
m_javaGlue->m_getPluginClass = GetJMethod(env, clazz, "getPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;");
m_javaGlue->m_showFullScreenPlugin = GetJMethod(env, clazz, "showFullScreenPlugin", "(Landroid/webkit/ViewManager$ChildView;II)V");
m_javaGlue->m_hideFullScreenPlugin = GetJMethod(env, clazz, "hideFullScreenPlugin", "()V");
@@ -439,20 +496,40 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V");
m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;");
m_javaGlue->m_keepScreenOn = GetJMethod(env, clazz, "keepScreenOn", "(Z)V");
- m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V");
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");
#if ENABLE(VIDEO)
m_javaGlue->m_enterFullscreenForVideoLayer = GetJMethod(env, clazz, "enterFullscreenForVideoLayer", "(ILjava/lang/String;)V");
+ m_javaGlue->m_exitFullscreenVideo = GetJMethod(env, clazz, "exitFullscreenVideo", "()V");
#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", "(IIILandroid/webkit/WebViewCore$TextFieldInitData;)V");
+ m_javaGlue->m_chromeCanTakeFocus = GetJMethod(env, clazz, "chromeCanTakeFocus", "(I)Z");
+ m_javaGlue->m_chromeTakeFocus = GetJMethod(env, clazz, "chromeTakeFocus", "(I)V");
env->DeleteLocalRef(clazz);
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
+ jclass tfidClazz = env->FindClass("android/webkit/WebViewCore$TextFieldInitData");
+ m_textFieldInitDataGlue->m_fieldPointer = env->GetFieldID(tfidClazz, "mFieldPointer", "I");
+ m_textFieldInitDataGlue->m_text = env->GetFieldID(tfidClazz, "mText", "Ljava/lang/String;");
+ m_textFieldInitDataGlue->m_type = env->GetFieldID(tfidClazz, "mType", "I");
+ m_textFieldInitDataGlue->m_isSpellCheckEnabled = env->GetFieldID(tfidClazz, "mIsSpellCheckEnabled", "Z");
+ m_textFieldInitDataGlue->m_isTextFieldNext = env->GetFieldID(tfidClazz, "mIsTextFieldNext", "Z");
+ m_textFieldInitDataGlue->m_isTextFieldPrev = env->GetFieldID(tfidClazz, "mIsTextFieldPrev", "Z");
+ m_textFieldInitDataGlue->m_isAutoCompleteEnabled = env->GetFieldID(tfidClazz, "mIsAutoCompleteEnabled", "Z");
+ m_textFieldInitDataGlue->m_name = env->GetFieldID(tfidClazz, "mName", "Ljava/lang/String;");
+ m_textFieldInitDataGlue->m_label = env->GetFieldID(tfidClazz, "mLabel", "Ljava/lang/String;");
+ m_textFieldInitDataGlue->m_maxLength = env->GetFieldID(tfidClazz, "mMaxLength", "I");
+ m_textFieldInitDataGlue->m_contentBounds = env->GetFieldID(tfidClazz, "mContentBounds", "Landroid/graphics/Rect;");
+ m_textFieldInitDataGlue->m_nodeLayerId = env->GetFieldID(tfidClazz, "mNodeLayerId", "I");
+ m_textFieldInitDataGlue->m_contentRect = env->GetFieldID(tfidClazz, "mContentRect", "Landroid/graphics/Rect;");
+ m_textFieldInitDataGlue->m_constructor = GetJMethod(env, tfidClazz, "<init>", "()V");
+ env->DeleteLocalRef(tfidClazz);
+
PageGroup::setShouldTrackVisitedLinks(true);
clearContent();
@@ -463,22 +540,23 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
WebViewCore::addInstance(this);
-#if USE(CHROME_NETWORK_STACK)
AndroidNetworkLibraryImpl::InitWithApplicationContext(env, 0);
-#endif
-#if USE(V8)
+ // increase the font cache size beyond the standard system setting
+ SkGraphics::SetFontCacheLimit(1572864); // 1572864 bytes == 1.5 MB
+
// Static initialisation of certain important V8 static data gets performed at system startup when
// libwebcore gets loaded. We now need to associate the WebCore thread with V8 to complete
// initialisation.
v8::V8::Initialize();
-#endif
// Configure any RuntimeEnabled features that we need to change from their default now.
// See WebCore/bindings/generic/RuntimeEnabledFeatures.h
// HTML5 History API
RuntimeEnabledFeatures::setPushStateEnabled(true);
+ if (m_mainFrame)
+ m_mainFrame->settings()->setMinDOMTimerInterval(FOREGROUND_TIMER_INTERVAL);
}
WebViewCore::~WebViewCore()
@@ -494,24 +572,40 @@ WebViewCore::~WebViewCore()
m_javaGlue->m_obj = 0;
}
delete m_javaGlue;
- delete m_frameCacheKit;
- delete m_navPictureKit;
}
WebViewCore* WebViewCore::getWebViewCore(const WebCore::FrameView* view)
{
- return getWebViewCore(static_cast<const WebCore::ScrollView*>(view));
+ if (!view)
+ return 0;
+ if (view->platformWidget())
+ return static_cast<WebFrameView*>(view->platformWidget())->webViewCore();
+ Frame* frame = view->frame();
+ while (Frame* parent = frame->tree()->parent())
+ frame = parent;
+ WebFrameView* webFrameView = 0;
+ if (frame && frame->view())
+ webFrameView = static_cast<WebFrameView*>(frame->view()->platformWidget());
+ if (!webFrameView)
+ return 0;
+ return webFrameView->webViewCore();
}
WebViewCore* WebViewCore::getWebViewCore(const WebCore::ScrollView* view)
{
if (!view)
return 0;
-
- WebFrameView* webFrameView = static_cast<WebFrameView*>(view->platformWidget());
- if (!webFrameView)
- return 0;
- return webFrameView->webViewCore();
+ if (view->platformWidget())
+ return static_cast<WebFrameView*>(view->platformWidget())->webViewCore();
+ const FrameView* frameView = 0;
+ if (view->isFrameView())
+ frameView = static_cast<const FrameView*>(view);
+ else {
+ frameView = static_cast<const FrameView*>(view->root());
+ if (!frameView)
+ return 0;
+ }
+ return getWebViewCore(frameView);
}
static bool layoutIfNeededRecursive(WebCore::Frame* f)
@@ -522,84 +616,35 @@ static bool layoutIfNeededRecursive(WebCore::Frame* f)
WebCore::FrameView* v = f->view();
if (!v)
return true;
-
- if (v->needsLayout())
- v->layout(f->tree()->parent());
-
- WebCore::Frame* child = f->tree()->firstChild();
- bool success = true;
- while (child) {
- success &= layoutIfNeededRecursive(child);
- child = child->tree()->nextSibling();
- }
-
- return success && !v->needsLayout();
-}
-
-CacheBuilder& WebViewCore::cacheBuilder()
-{
- return FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder();
+ v->updateLayoutAndStyleIfNeededRecursive();
+ return !v->needsLayout();
}
WebCore::Node* WebViewCore::currentFocus()
{
- return cacheBuilder().currentFocus();
+ return focusedFrame()->document()->focusedNode();
}
-void WebViewCore::recordPicture(SkPicture* picture)
+void WebViewCore::layout()
{
- // if there is no document yet, just return
- if (!m_mainFrame->document()) {
- DBG_NAV_LOG("no document");
- return;
- }
- // Call layout to ensure that the contentWidth and contentHeight are correct
- if (!layoutIfNeededRecursive(m_mainFrame)) {
- DBG_NAV_LOG("layout failed");
- return;
- }
- // draw into the picture's recording canvas
- WebCore::FrameView* view = m_mainFrame->view();
- DBG_NAV_LOGD("view=(w=%d,h=%d)", view->contentsWidth(),
- view->contentsHeight());
- SkAutoPictureRecord arp(picture, view->contentsWidth(),
- view->contentsHeight(), PICT_RECORD_FLAGS);
- SkAutoMemoryUsageProbe mup(__FUNCTION__);
-
- WebCore::PlatformGraphicsContext pgc(arp.getRecordingCanvas());
- WebCore::GraphicsContext gc(&pgc);
- view->platformWidget()->draw(&gc, WebCore::IntRect(0, 0,
- view->contentsWidth(), view->contentsHeight()));
-}
+ TRACE_METHOD();
-void WebViewCore::recordPictureSet(PictureSet* content)
-{
// if there is no document yet, just return
if (!m_mainFrame->document()) {
- DBG_SET_LOG("!m_mainFrame->document()");
- return;
- }
- if (m_addInval.isEmpty()) {
- DBG_SET_LOG("m_addInval.isEmpty()");
+ ALOGV("!m_mainFrame->document()");
return;
}
+
// Call layout to ensure that the contentWidth and contentHeight are correct
// it's fine for layout to gather invalidates, but defeat sending a message
// back to java to call webkitDraw, since we're already in the middle of
// doing that
- m_skipContentDraw = true;
bool success = layoutIfNeededRecursive(m_mainFrame);
- m_skipContentDraw = false;
// We may be mid-layout and thus cannot draw.
if (!success)
return;
- { // collect WebViewCoreRecordTimeCounter after layoutIfNeededRecursive
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreRecordTimeCounter);
-#endif
-
// if the webkit page dimensions changed, discard the pictureset and redraw.
WebCore::FrameView* view = m_mainFrame->view();
int width = view->contentsWidth();
@@ -650,6 +695,8 @@ void WebViewCore::recordPictureSet(PictureSet* content)
// If the new total is larger than the content, resize the view to include
// all the content.
if (!contentRect.contains(total)) {
+ // TODO: Does this ever happen? Is this needed now that we don't flatten
+ // frames?
// Resize the view to change the overflow clip.
view->resize(total.fRight, total.fBottom);
@@ -658,159 +705,27 @@ void WebViewCore::recordPictureSet(PictureSet* content)
view->forceLayout();
// Relayout similar to above
- m_skipContentDraw = true;
- bool success = layoutIfNeededRecursive(m_mainFrame);
- m_skipContentDraw = false;
- if (!success)
- return;
-
- // Set the computed content width
- width = view->contentsWidth();
- height = view->contentsHeight();
+ layoutIfNeededRecursive(m_mainFrame);
}
+}
- if (cacheBuilder().pictureSetDisabled())
- content->clear();
-
-#if USE(ACCELERATED_COMPOSITING)
- // The invals are not always correct when the content size has changed. For
- // now, let's just reset the inval so that it invalidates the entire content
- // -- the pictureset will be fully repainted, tiles will be marked dirty and
- // will have to be repainted.
-
- // FIXME: the webkit invals ought to have been enough...
- if (content->width() != width || content->height() != height) {
- SkIRect r;
- r.fLeft = 0;
- r.fTop = 0;
- r.fRight = width;
- r.fBottom = height;
- m_addInval.setRect(r);
- }
-#endif
-
- content->setDimensions(width, height, &m_addInval);
-
- // Add the current inval rects to the PictureSet, and rebuild it.
- content->add(m_addInval, 0, 0, false);
+void WebViewCore::recordPicturePile()
+{
+ // if the webkit page dimensions changed, discard the pictureset and redraw.
+ WebCore::FrameView* view = m_mainFrame->view();
+ int width = view ? view->contentsWidth() : 0;
+ int height = view ? view->contentsHeight() : 0;
- // If we have too many invalidations, just get the area bounds
- SkRegion::Iterator iterator(m_addInval);
- int nbInvals = 0;
- while (!iterator.done()) {
- iterator.next();
- nbInvals++;
- if (nbInvals > MAX_INVALIDATIONS)
- break;
- }
- if (nbInvals > MAX_INVALIDATIONS) {
- SkIRect r = m_addInval.getBounds();
- m_addInval.setRect(r);
- }
+ m_content.setSize(IntSize(width, height));
// Rebuild the pictureset (webkit repaint)
- rebuildPictureSet(content);
- } // WebViewCoreRecordTimeCounter
-
- WebCore::Node* oldFocusNode = currentFocus();
- m_frameCacheOutOfDate = true;
- WebCore::IntRect oldBounds;
- int oldSelStart = 0;
- int oldSelEnd = 0;
- if (oldFocusNode) {
- oldBounds = oldFocusNode->getRect();
- RenderObject* renderer = oldFocusNode->renderer();
- if (renderer && (renderer->isTextArea() || renderer->isTextField())) {
- WebCore::RenderTextControl* rtc =
- static_cast<WebCore::RenderTextControl*>(renderer);
- oldSelStart = rtc->selectionStart();
- oldSelEnd = rtc->selectionEnd();
- }
- } else
- oldBounds = WebCore::IntRect(0,0,0,0);
- unsigned latestVersion = 0;
- if (m_check_domtree_version) {
- // as domTreeVersion only increment, we can just check the sum to see
- // whether we need to update the frame cache
- for (Frame* frame = m_mainFrame; frame; frame = frame->tree()->traverseNext()) {
- const Document* doc = frame->document();
- latestVersion += doc->domTreeVersion() + doc->styleVersion();
- }
- }
- DBG_NAV_LOGD("m_lastFocused=%p oldFocusNode=%p"
- " m_lastFocusedBounds={%d,%d,%d,%d} oldBounds={%d,%d,%d,%d}"
- " m_lastFocusedSelection={%d,%d} oldSelection={%d,%d}"
- " m_check_domtree_version=%s latestVersion=%d m_domtree_version=%d",
- m_lastFocused, oldFocusNode,
- m_lastFocusedBounds.x(), m_lastFocusedBounds.y(),
- m_lastFocusedBounds.width(), m_lastFocusedBounds.height(),
- oldBounds.x(), oldBounds.y(), oldBounds.width(), oldBounds.height(),
- m_lastFocusedSelStart, m_lastFocusedSelEnd, oldSelStart, oldSelEnd,
- m_check_domtree_version ? "true" : "false",
- latestVersion, m_domtree_version);
- if (m_lastFocused == oldFocusNode && m_lastFocusedBounds == oldBounds
- && m_lastFocusedSelStart == oldSelStart
- && m_lastFocusedSelEnd == oldSelEnd
- && !m_findIsUp
- && (!m_check_domtree_version || latestVersion == m_domtree_version))
- {
- return;
- }
- m_focusBoundsChanged |= m_lastFocused == oldFocusNode
- && m_lastFocusedBounds != oldBounds;
- m_lastFocused = oldFocusNode;
- m_lastFocusedBounds = oldBounds;
- m_lastFocusedSelStart = oldSelStart;
- m_lastFocusedSelEnd = oldSelEnd;
- m_domtree_version = latestVersion;
- DBG_NAV_LOG("call updateFrameCache");
- updateFrameCache();
- if (m_findIsUp) {
- LOG_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()) {
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_sendFindAgain);
- checkException(env);
- }
- }
-}
-
-// note: updateCursorBounds is called directly by the WebView thread
-// This needs to be called each time we call CachedRoot::setCursor() with
-// non-null CachedNode/CachedFrame, since otherwise the WebViewCore's data
-// about the cursor is incorrect. When we call setCursor(0,0), we need
-// to set hasCursorBounds to false.
-void WebViewCore::updateCursorBounds(const CachedRoot* root,
- const CachedFrame* cachedFrame, const CachedNode* cachedNode)
-{
- LOG_ASSERT(root, "updateCursorBounds: root cannot be null");
- LOG_ASSERT(cachedNode, "updateCursorBounds: cachedNode cannot be null");
- LOG_ASSERT(cachedFrame, "updateCursorBounds: cachedFrame cannot be null");
- gCursorBoundsMutex.lock();
- m_hasCursorBounds = !cachedNode->isHidden();
- // If m_hasCursorBounds is false, we never look at the other
- // values, so do not bother setting them.
- if (m_hasCursorBounds) {
- WebCore::IntRect bounds = cachedNode->bounds(cachedFrame);
- if (m_cursorBounds != bounds)
- DBG_NAV_LOGD("new cursor bounds=(%d,%d,w=%d,h=%d)",
- bounds.x(), bounds.y(), bounds.width(), bounds.height());
- m_cursorBounds = bounds;
- m_cursorHitBounds = cachedNode->hitBounds(cachedFrame);
- m_cursorFrame = cachedFrame->framePointer();
- root->getSimulatedMousePosition(&m_cursorLocation);
- m_cursorNode = cachedNode->nodePointer();
- }
- gCursorBoundsMutex.unlock();
+ m_content.updatePicturesIfNeeded(this);
}
void WebViewCore::clearContent()
{
- DBG_SET_LOG("");
- m_content.clear();
- m_addInval.setEmpty();
- m_rebuildInval.setEmpty();
+ m_content.reset();
+ updateLocale();
}
bool WebViewCore::focusBoundsChanged()
@@ -820,75 +735,82 @@ bool WebViewCore::focusBoundsChanged()
return result;
}
-SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval)
+void WebViewCore::paintContents(WebCore::GraphicsContext* gc, WebCore::IntRect& dirty)
{
WebCore::FrameView* view = m_mainFrame->view();
- int width = view->contentsWidth();
- int height = view->contentsHeight();
- SkPicture* picture = new SkPicture();
- SkAutoPictureRecord arp(picture, width, height, PICT_RECORD_FLAGS);
- SkAutoMemoryUsageProbe mup(__FUNCTION__);
- SkCanvas* recordingCanvas = arp.getRecordingCanvas();
+ if (!view) {
+ gc->setFillColor(WebCore::Color::white, WebCore::ColorSpaceDeviceRGB);
+ gc->fillColor();
+ return;
+ }
- WebCore::PlatformGraphicsContext pgc(recordingCanvas);
- WebCore::GraphicsContext gc(&pgc);
IntPoint origin = view->minimumScrollPosition();
- WebCore::IntRect drawArea(inval.fLeft + origin.x(), inval.fTop + origin.y(),
- inval.width(), inval.height());
- recordingCanvas->translate(-drawArea.x(), -drawArea.y());
- recordingCanvas->save();
- view->platformWidget()->draw(&gc, drawArea);
- m_rebuildInval.op(inval, SkRegion::kUnion_Op);
- DBG_SET_LOGD("m_rebuildInval={%d,%d,r=%d,b=%d}",
- m_rebuildInval.getBounds().fLeft, m_rebuildInval.getBounds().fTop,
- m_rebuildInval.getBounds().fRight, m_rebuildInval.getBounds().fBottom);
-
- return picture;
+ IntRect drawArea = dirty;
+ gc->translate(-origin.x(), -origin.y());
+ drawArea.move(origin.x(), origin.y());
+ view->platformWidget()->draw(gc, drawArea);
}
-void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
+void WebViewCore::setPrerenderingEnabled(bool enable)
{
- WebCore::FrameView* view = m_mainFrame->view();
-
-#ifdef FAST_PICTURESET
- WTF::Vector<Bucket*>* buckets = pictureSet->bucketsToUpdate();
-
- for (unsigned int i = 0; i < buckets->size(); i++) {
- Bucket* bucket = (*buckets)[i];
- for (unsigned int j = 0; j < bucket->size(); j++) {
- BucketPicture& bucketPicture = (*bucket)[j];
- const SkIRect& inval = bucketPicture.mRealArea;
- SkPicture* picture = rebuildPicture(inval);
- SkSafeUnref(bucketPicture.mPicture);
- bucketPicture.mPicture = picture;
- }
- }
- buckets->clear();
-#else
- size_t size = pictureSet->size();
- for (size_t index = 0; index < size; index++) {
- if (pictureSet->upToDate(index))
- continue;
- const SkIRect& inval = pictureSet->bounds(index);
- DBG_SET_LOGD("pictSet=%p [%d] {%d,%d,w=%d,h=%d}", pictureSet, index,
- inval.fLeft, inval.fTop, inval.width(), inval.height());
- pictureSet->setPicture(index, rebuildPicture(inval));
- }
+ MutexLocker locker(m_prerenderLock);
+ m_prerenderEnabled = enable;
+}
- pictureSet->validate(__FUNCTION__);
-#endif
+bool WebViewCore::prerenderingEnabled()
+{
+ MutexLocker locker(m_prerenderLock);
+ return m_prerenderEnabled;
}
-bool WebViewCore::updateLayers(LayerAndroid* layers)
+SkCanvas* WebViewCore::createPrerenderCanvas(PrerenderedInval* prerendered)
{
- // We update the layers
- ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
- GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
- if (root) {
- LayerAndroid* updatedLayer = root->contentLayer();
- return layers->updateWithTree(updatedLayer);
- }
- return true;
+ // Has WebView disabled prerenders (not attached, etc...)?
+ if (!prerenderingEnabled())
+ return 0;
+ // Does this WebView have focus?
+ if (!m_mainFrame->page()->focusController()->isActive())
+ return 0;
+ // Are we scrolling?
+ if (currentTimeMS() - m_scrollSetTime < PRERENDER_AFTER_SCROLL_DELAY)
+ return 0;
+ // Do we have anything to render?
+ if (prerendered->area.isEmpty())
+ return 0;
+ FloatRect scaleTemp(m_scrollOffsetX, m_scrollOffsetY, m_screenWidth, m_screenHeight);
+ scaleTemp.scale(m_scale);
+ IntRect visibleTileClip = enclosingIntRect(scaleTemp);
+ FloatRect scaledArea = prerendered->area;
+ scaledArea.scale(m_scale);
+ IntRect enclosingScaledArea = enclosingIntRect(scaledArea);
+ if (enclosingScaledArea.isEmpty())
+ return 0;
+ // "round out" the screen to tile boundaries so that we can clip yet still
+ // cover any visible tiles with the prerender
+ int tw = TilesManager::tileWidth();
+ int th = TilesManager::tileHeight();
+ float left = tw * (int) (visibleTileClip.x() / tw);
+ float top = th * (int) (visibleTileClip.y() / th);
+ float right = tw * (int) ceilf(visibleTileClip.maxX() / (float) tw);
+ float bottom = th * (int) ceilf(visibleTileClip.maxY() / (float) th);
+ visibleTileClip = IntRect(left, top, right - left, bottom - top);
+ enclosingScaledArea.intersect(visibleTileClip);
+ if (enclosingScaledArea.isEmpty())
+ return 0;
+ prerendered->screenArea = enclosingScaledArea;
+ FloatRect enclosingDocArea(enclosingScaledArea);
+ enclosingDocArea.scale(1 / m_scale);
+ prerendered->area = enclosingIntRect(enclosingDocArea);
+ if (prerendered->area.isEmpty())
+ return 0;
+ prerendered->bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ enclosingScaledArea.width(),
+ enclosingScaledArea.height());
+ prerendered->bitmap.allocPixels();
+ SkCanvas* bitmapCanvas = new SkCanvas(prerendered->bitmap);
+ bitmapCanvas->scale(m_scale, m_scale);
+ bitmapCanvas->translate(-enclosingDocArea.x(), -enclosingDocArea.y());
+ return bitmapCanvas;
}
void WebViewCore::notifyAnimationStarted()
@@ -902,93 +824,113 @@ void WebViewCore::notifyAnimationStarted()
}
-BaseLayerAndroid* WebViewCore::createBaseLayer(SkRegion* region)
+BaseLayerAndroid* WebViewCore::createBaseLayer(GraphicsLayerAndroid* root)
{
- BaseLayerAndroid* base = new BaseLayerAndroid();
- base->setContent(m_content);
+ // We set the background color
+ Color background = Color::white;
- m_skipContentDraw = true;
- bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
- m_skipContentDraw = false;
- // Layout only fails if called during a layout.
- LOG_ASSERT(layoutSucceeded, "Can never be called recursively");
+ bool bodyHasFixedBackgroundImage = false;
+ bool bodyHasCSSBackground = false;
-#if USE(ACCELERATED_COMPOSITING)
- // We set the background color
if (m_mainFrame && m_mainFrame->document()
&& m_mainFrame->document()->body()) {
+
Document* document = m_mainFrame->document();
RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body());
if (style->hasBackground()) {
- Color color = style->visitedDependentColor(CSSPropertyBackgroundColor);
- if (color.isValid() && color.alpha() > 0)
- base->setBackgroundColor(color);
+ background = style->visitedDependentColor(CSSPropertyBackgroundColor);
+ bodyHasCSSBackground = true;
+ }
+ WebCore::FrameView* view = m_mainFrame->view();
+ if (view) {
+ Color viewBackground = view->baseBackgroundColor();
+ background = bodyHasCSSBackground ? viewBackground.blend(background) : viewBackground;
}
+ if (style->hasFixedBackgroundImage()) {
+ Image* backgroundImage = FixedBackgroundImageLayerAndroid::GetCachedImage(style);
+ if (backgroundImage && backgroundImage->width() > 1 && backgroundImage->height() > 1)
+ bodyHasFixedBackgroundImage = true;
+ }
+ }
+
+ PicturePileLayerContent* content = new PicturePileLayerContent(m_content);
+ m_content.clearPrerenders();
+
+ BaseLayerAndroid* realBase = 0;
+ LayerAndroid* base = 0;
+
+ //If we have a fixed background image on the body element, the fixed image
+ // will be contained in the PictureSet (the content object), and the foreground
+ //of the body element will be moved to a layer.
+ //In that case, let's change the hierarchy to obtain:
+ //
+ //BaseLayerAndroid
+ // \- FixedBackgroundBaseLayerAndroid (fixed positioning)
+ // \- ForegroundBaseLayerAndroid
+ // \- root layer (webkit composited tree)
+
+ if (bodyHasFixedBackgroundImage) {
+ base = new ForegroundBaseLayerAndroid(0);
+ base->setSize(content->width(), content->height());
+
+ Document* document = m_mainFrame->document();
+ RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body());
+
+ FixedBackgroundImageLayerAndroid* baseBackground =
+ new FixedBackgroundImageLayerAndroid(style, content->width(), content->height());
+
+ realBase = new BaseLayerAndroid(0);
+ realBase->setSize(content->width(), content->height());
+ realBase->addChild(baseBackground);
+ realBase->addChild(base);
+ baseBackground->unref();
+ base->unref();
+ } else {
+ realBase = new BaseLayerAndroid(content);
+ base = realBase;
}
+ realBase->setBackgroundColor(background);
+
+ SkSafeUnref(content);
+
// We update the layers
- ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
- GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
if (root) {
LayerAndroid* copyLayer = new LayerAndroid(*root->contentLayer());
base->addChild(copyLayer);
copyLayer->unref();
root->contentLayer()->clearDirtyRegion();
}
-#endif
- return base;
+ return realBase;
}
-BaseLayerAndroid* WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
+BaseLayerAndroid* WebViewCore::recordContent(SkIPoint* point)
{
- DBG_SET_LOG("start");
- // If there is a pending style recalculation, just return.
- if (m_mainFrame->document()->isPendingStyleRecalc()) {
- DBG_SET_LOGD("recordContent: pending style recalc, ignoring.");
- return 0;
- }
- float progress = (float) m_mainFrame->page()->progress()->estimatedProgress();
- m_progressDone = progress <= 0.0f || progress >= 1.0f;
- recordPictureSet(&m_content);
- if (!m_progressDone && m_content.isEmpty()) {
- DBG_SET_LOGD("empty (progress=%g)", progress);
- return 0;
- }
- region->set(m_addInval);
- m_addInval.setEmpty();
+ m_skipContentDraw = true;
+ layout();
+ ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
+ GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
+ m_skipContentDraw = false;
+ recordPicturePile();
+
+ BaseLayerAndroid* baseLayer = createBaseLayer(root);
+
+ baseLayer->markAsDirty(m_content.dirtyRegion());
+ m_content.dirtyRegion().setEmpty();
#if USE(ACCELERATED_COMPOSITING)
#else
- region->op(m_rebuildInval, SkRegion::kUnion_Op);
+ baseLayer->markAsDirty(m_rebuildInval);
#endif
- m_rebuildInval.setEmpty();
- point->fX = m_content.width();
- point->fY = m_content.height();
- 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");
+ point->fX = m_content.size().width();
+ point->fY = m_content.size().height();
- return createBaseLayer(region);
-}
-
-void WebViewCore::splitContent(PictureSet* content)
-{
-#ifdef FAST_PICTURESET
-#else
- bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
- LOG_ASSERT(layoutSucceeded, "Can never be called recursively");
- content->split(&m_content);
- rebuildPictureSet(&m_content);
- content->set(m_content);
-#endif // FAST_PICTURESET
+ return baseLayer;
}
void WebViewCore::scrollTo(int x, int y, bool animate)
{
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
-
-// LOGD("WebViewCore::scrollTo(%d %d)\n", x, y);
+ 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);
@@ -1001,7 +943,7 @@ void WebViewCore::scrollTo(int x, int y, bool animate)
void WebViewCore::sendNotifyProgressFinished()
{
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+ 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())
@@ -1012,7 +954,7 @@ void WebViewCore::sendNotifyProgressFinished()
void WebViewCore::viewInvalidate(const WebCore::IntRect& rect)
{
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+ 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())
@@ -1033,26 +975,12 @@ void WebViewCore::contentDraw()
checkException(env);
}
-void WebViewCore::layersDraw()
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- AutoJObject javaObject = m_javaGlue->object(env);
- if (!javaObject.get())
- return;
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_layersDraw);
- checkException(env);
-}
-
void WebViewCore::contentInvalidate(const WebCore::IntRect &r)
{
- DBG_SET_LOGD("rect={%d,%d,w=%d,h=%d}", r.x(), r.y(), r.width(), r.height());
- SkIRect rect(r);
- if (!rect.intersect(0, 0, INT_MAX, INT_MAX))
- return;
- m_addInval.op(rect, SkRegion::kUnion_Op);
- DBG_SET_LOGD("m_addInval={%d,%d,r=%d,b=%d}",
- m_addInval.getBounds().fLeft, m_addInval.getBounds().fTop,
- m_addInval.getBounds().fRight, m_addInval.getBounds().fBottom);
+ IntPoint origin = m_mainFrame->view()->minimumScrollPosition();
+ IntRect dirty = r;
+ dirty.move(-origin.x(), -origin.y());
+ m_content.invalidate(dirty);
if (!m_skipContentDraw)
contentDraw();
}
@@ -1072,19 +1000,9 @@ void WebViewCore::offInvalidate(const WebCore::IntRect &r)
contentInvalidate(r);
}
-static int pin_pos(int x, int width, int targetWidth)
-{
- if (x + width > targetWidth)
- x = targetWidth - width;
- if (x < 0)
- x = 0;
- return x;
-}
-
void WebViewCore::didFirstLayout()
{
- DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+ 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);
@@ -1094,7 +1012,7 @@ void WebViewCore::didFirstLayout()
const WebCore::KURL& url = m_mainFrame->document()->url();
if (url.isEmpty())
return;
- LOGV("::WebCore:: didFirstLayout %s", url.string().ascii().data());
+ ALOGV("::WebCore:: didFirstLayout %s", url.string().ascii().data());
WebCore::FrameLoadType loadType = m_mainFrame->loader()->loadType();
@@ -1108,17 +1026,11 @@ void WebViewCore::didFirstLayout()
// a newly-loaded page.
|| loadType == WebCore::FrameLoadTypeSame);
checkException(env);
-
- DBG_NAV_LOG("call updateFrameCache");
- m_check_domtree_version = false;
- updateFrameCache();
- m_history.setDidFirstLayout(true);
}
void WebViewCore::updateViewport()
{
- DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+ 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);
@@ -1130,8 +1042,7 @@ void WebViewCore::updateViewport()
void WebViewCore::restoreScale(float scale, float textWrapScale)
{
- DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+ 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);
@@ -1143,8 +1054,7 @@ void WebViewCore::restoreScale(float scale, float textWrapScale)
void WebViewCore::needTouchEvents(bool need)
{
- DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+ ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
#if ENABLE(TOUCH_EVENTS)
JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -1162,26 +1072,9 @@ void WebViewCore::needTouchEvents(bool need)
#endif
}
-void WebViewCore::requestKeyboardWithSelection(const WebCore::Node* node,
- int selStart, int selEnd)
-{
- 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();
- 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__);
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+ 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);
@@ -1193,42 +1086,15 @@ void WebViewCore::requestKeyboard(bool showKeyboard)
void WebViewCore::notifyProgressFinished()
{
- m_check_domtree_version = true;
sendNotifyProgressFinished();
}
-void WebViewCore::doMaxScroll(CacheBuilder::Direction dir)
-{
- int dx = 0, dy = 0;
-
- switch (dir) {
- case CacheBuilder::LEFT:
- dx = -m_maxXScroll;
- break;
- case CacheBuilder::UP:
- dy = -m_maxYScroll;
- break;
- case CacheBuilder::RIGHT:
- dx = m_maxXScroll;
- break;
- case CacheBuilder::DOWN:
- dy = m_maxYScroll;
- break;
- case CacheBuilder::UNINITIALIZED:
- default:
- LOG_ASSERT(0, "unexpected focus selector");
- }
- WebCore::FrameView* view = m_mainFrame->view();
- this->scrollTo(view->scrollX() + dx, view->scrollY() + dy, true);
-}
-
-void WebViewCore::setScrollOffset(int moveGeneration, bool sendScrollEvent, int dx, int dy)
+void WebViewCore::setScrollOffset(bool sendScrollEvent, int dx, int dy)
{
- DBG_NAV_LOGD("{%d,%d} m_scrollOffset=(%d,%d), sendScrollEvent=%d", dx, dy,
- m_scrollOffsetX, m_scrollOffsetY, sendScrollEvent);
if (m_scrollOffsetX != dx || m_scrollOffsetY != dy) {
m_scrollOffsetX = dx;
m_scrollOffsetY = dy;
+ m_scrollSetTime = currentTimeMS();
// The visible rect is located within our coordinate space so it
// contains the actual scroll position. Setting the location makes hit
// testing work correctly.
@@ -1259,19 +1125,10 @@ void WebViewCore::setScrollOffset(int moveGeneration, bool sendScrollEvent, int
// update the currently visible screen
sendPluginVisibleScreen();
}
- gCursorBoundsMutex.lock();
- bool hasCursorBounds = m_hasCursorBounds;
- Frame* frame = (Frame*) m_cursorFrame;
- IntPoint location = m_cursorLocation;
- gCursorBoundsMutex.unlock();
- if (!hasCursorBounds)
- return;
- moveMouseIfLatest(moveGeneration, frame, location.x(), location.y());
}
void WebViewCore::setGlobalBounds(int x, int y, int h, int v)
{
- DBG_NAV_LOGD("{%d,%d}", x, y);
m_mainFrame->view()->platformWidget()->setWindowBounds(x, y, h, v);
}
@@ -1290,9 +1147,6 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
int osw = m_screenWidth;
int osh = m_screenHeight;
int otw = m_textWrapWidth;
- float oldScale = m_scale;
- 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;
m_textWrapWidth = textWrapWidth;
@@ -1311,11 +1165,8 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
if (ow != width || (!ignoreHeight && oh != height) || reflow) {
WebCore::RenderObject *r = m_mainFrame->contentRenderer();
- DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
- screenWidth, screenHeight);
if (r) {
WebCore::IntPoint anchorPoint = WebCore::IntPoint(anchorX, anchorY);
- DBG_NAV_LOGD("anchorX=%d anchorY=%d", anchorX, anchorY);
RefPtr<WebCore::Node> node;
WebCore::IntRect bounds;
WebCore::IntPoint offset;
@@ -1327,11 +1178,19 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
m_mainFrame->eventHandler()->hitTestResultAtPoint(
anchorPoint, false);
node = hitTestResult.innerNode();
+ if (node && !node->isTextNode()) {
+ // If the hitTestResultAtPoint didn't find a suitable node
+ // for anchoring, try again with some slop.
+ static const int HIT_SLOP = 30;
+ anchorPoint.move(HIT_SLOP, HIT_SLOP);
+ hitTestResult =
+ m_mainFrame->eventHandler()->hitTestResultAtPoint(
+ anchorPoint, false);
+ node = hitTestResult.innerNode();
+ }
}
if (node) {
bounds = node->getRect();
- DBG_NAV_LOGD("ob:(x=%d,y=%d,w=%d,h=%d)",
- bounds.x(), bounds.y(), bounds.width(), bounds.height());
// sites like nytimes.com insert a non-standard tag <nyt_text>
// in the html. If it is the HitTestResult, it may have zero
// width and height. In this case, use its parent node.
@@ -1339,8 +1198,6 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
node = node->parentOrHostNode();
if (node) {
bounds = node->getRect();
- DBG_NAV_LOGD("found a zero width node and use its parent, whose ob:(x=%d,y=%d,w=%d,h=%d)",
- bounds.x(), bounds.y(), bounds.width(), bounds.height());
}
}
}
@@ -1361,9 +1218,6 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
// scroll to restore current screen center
if (node && node->inDocument()) {
const WebCore::IntRect& newBounds = node->getRect();
- DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
- "h=%d)", newBounds.x(), newBounds.y(),
- newBounds.width(), newBounds.height());
if ((osw && osh && bounds.width() && bounds.height())
&& (bounds != newBounds)) {
WebCore::FrameView* view = m_mainFrame->view();
@@ -1440,13 +1294,6 @@ void WebViewCore::dumpRenderTree(bool useFile)
#endif
}
-void WebViewCore::dumpNavTree()
-{
-#if DUMP_NAV_CACHE
- cacheBuilder().mDebug.print();
-#endif
-}
-
HTMLElement* WebViewCore::retrieveElement(int x, int y,
const QualifiedName& tagName)
{
@@ -1455,12 +1302,12 @@ HTMLElement* WebViewCore::retrieveElement(int x, int y,
DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
IntSize(1, 1));
if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
- LOGE("Should not happen: no in document Node found");
+ ALOGE("Should not happen: no in document Node found");
return 0;
}
const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
if (list.isEmpty()) {
- LOGE("Should not happen: no rect-based-test nodes found");
+ ALOGE("Should not happen: no rect-based-test nodes found");
return 0;
}
Node* node = hitTestResult.innerNode();
@@ -1469,9 +1316,6 @@ HTMLElement* WebViewCore::retrieveElement(int x, int y,
|| !element->hasTagName(tagName))) {
element = element->parentNode();
}
- DBG_NAV_LOGD("node=%p element=%p x=%d y=%d nodeName=%s tagName=%s", node,
- element, x, y, node->nodeName().utf8().data(),
- element ? ((Element*) element)->tagName().utf8().data() : "<none>");
return static_cast<WebCore::HTMLElement*>(element);
}
@@ -1489,8 +1333,10 @@ HTMLImageElement* WebViewCore::retrieveImageElement(int x, int y)
WTF::String WebViewCore::retrieveHref(int x, int y)
{
- WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(x, y);
- return anchor ? anchor->href() : WTF::String();
+ // TODO: This is expensive, cache
+ HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
+ false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(1, 1));
+ return result.absoluteLinkURL();
}
WTF::String WebViewCore::retrieveAnchorText(int x, int y)
@@ -1501,14 +1347,16 @@ WTF::String WebViewCore::retrieveAnchorText(int x, int y)
WTF::String WebViewCore::retrieveImageSource(int x, int y)
{
- HTMLImageElement* image = retrieveImageElement(x, y);
- return image ? image->src().string() : WTF::String();
+ // TODO: This is expensive, cache
+ HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
+ false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(1, 1));
+ return result.absoluteImageURL();
}
WTF::String WebViewCore::requestLabel(WebCore::Frame* frame,
WebCore::Node* node)
{
- if (node && CacheBuilder::validNode(m_mainFrame, frame, node)) {
+ if (node && validNode(m_mainFrame, frame, node)) {
RefPtr<WebCore::NodeList> list = node->document()->getElementsByTagName("label");
unsigned length = list->length();
for (unsigned i = 0; i < length; i++) {
@@ -1532,17 +1380,18 @@ WTF::String WebViewCore::requestLabel(WebCore::Frame* frame,
static bool isContentEditable(const WebCore::Node* node)
{
- if (!node) return false;
- return node->document()->frame()->selection()->isContentEditable();
+ if (!node)
+ return false;
+ return node->isContentEditable();
}
// Returns true if the node is a textfield, textarea, or contentEditable
static bool isTextInput(const WebCore::Node* node)
{
- if (isContentEditable(node))
- return true;
if (!node)
return false;
+ if (isContentEditable(node))
+ return true;
WebCore::RenderObject* renderer = node->renderer();
return renderer && (renderer->isTextField() || renderer->isTextArea());
}
@@ -1560,107 +1409,9 @@ void WebViewCore::revealSelection()
focusedFrame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
}
-void WebViewCore::updateCacheOnNodeChange()
-{
- gCursorBoundsMutex.lock();
- bool hasCursorBounds = m_hasCursorBounds;
- Frame* frame = (Frame*) m_cursorFrame;
- Node* node = (Node*) m_cursorNode;
- IntRect bounds = m_cursorHitBounds;
- gCursorBoundsMutex.unlock();
- if (!hasCursorBounds || !node)
- return;
- if (CacheBuilder::validNode(m_mainFrame, frame, node)) {
- RenderObject* renderer = node->renderer();
- if (renderer && renderer->style()->visibility() != HIDDEN) {
- IntRect absBox = renderer->absoluteBoundingBoxRect();
- int globalX, globalY;
- CacheBuilder::GetGlobalOffset(frame, &globalX, &globalY);
- absBox.move(globalX, globalY);
- if (absBox == bounds)
- return;
- DBG_NAV_LOGD("absBox=(%d,%d,%d,%d) bounds=(%d,%d,%d,%d)",
- absBox.x(), absBox.y(), absBox.width(), absBox.height(),
- bounds.x(), bounds.y(), bounds.width(), bounds.height());
- }
- }
- DBG_NAV_LOGD("updateFrameCache node=%p", node);
- updateFrameCache();
-}
-
-void WebViewCore::updateFrameCache()
-{
- if (!m_frameCacheOutOfDate) {
- DBG_NAV_LOG("!m_frameCacheOutOfDate");
- return;
- }
-
- // If there is a pending style recalculation, do not update the frame cache.
- // Until the recalculation is complete, there may be internal objects that
- // are in an inconsistent state (such as font pointers).
- // In any event, there's not much point to updating the cache while a style
- // recalculation is pending, since it will simply have to be updated again
- // once the recalculation is complete.
- // TODO: Do we need to reschedule an update for after the style is recalculated?
- if (m_mainFrame && m_mainFrame->document() && m_mainFrame->document()->isPendingStyleRecalc()) {
- LOGW("updateFrameCache: pending style recalc, ignoring.");
- return;
- }
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreBuildNavTimeCounter);
-#endif
- m_frameCacheOutOfDate = false;
- m_temp = new CachedRoot();
- m_temp->init(m_mainFrame, &m_history);
-#if USE(ACCELERATED_COMPOSITING)
- GraphicsLayerAndroid* graphicsLayer = graphicsRootLayer();
- if (graphicsLayer)
- m_temp->setRootLayer(graphicsLayer->contentLayer());
-#endif
- CacheBuilder& builder = cacheBuilder();
- WebCore::Settings* settings = m_mainFrame->page()->settings();
- builder.allowAllTextDetection();
-#ifdef ANDROID_META_SUPPORT
- if (settings) {
- if (!settings->formatDetectionAddress())
- builder.disallowAddressDetection();
- if (!settings->formatDetectionEmail())
- builder.disallowEmailDetection();
- if (!settings->formatDetectionTelephone())
- builder.disallowPhoneDetection();
- }
-#endif
- builder.buildCache(m_temp);
- m_tempPict = new SkPicture();
- recordPicture(m_tempPict);
- m_temp->setPicture(m_tempPict);
- m_temp->setTextGeneration(m_textGeneration);
- WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
- m_temp->setVisibleRect(WebCore::IntRect(m_scrollOffsetX,
- m_scrollOffsetY, window->width(), window->height()));
- gFrameCacheMutex.lock();
- delete m_frameCacheKit;
- delete m_navPictureKit;
- m_frameCacheKit = m_temp;
- m_navPictureKit = m_tempPict;
- m_updatedFrameCache = true;
-#if DEBUG_NAV_UI
- const CachedNode* cachedFocusNode = m_frameCacheKit->currentFocus();
- DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p)",
- cachedFocusNode ? cachedFocusNode->index() : 0,
- cachedFocusNode ? cachedFocusNode->nodePointer() : 0);
-#endif
- gFrameCacheMutex.unlock();
-}
-
-void WebViewCore::updateFrameCacheIfLoading()
-{
- if (!m_check_domtree_version)
- updateFrameCache();
-}
-
struct TouchNodeData {
- Node* mNode;
+ Node* mUrlNode;
+ Node* mInnerNode;
IntRect mBounds;
};
@@ -1668,6 +1419,8 @@ struct TouchNodeData {
static IntRect getAbsoluteBoundingBox(Node* node) {
IntRect rect;
RenderObject* render = node->renderer();
+ if (!render)
+ return rect;
if (render->isRenderInline())
rect = toRenderInline(render)->linesVisualOverflowBoundingBox();
else if (render->isBox())
@@ -1675,30 +1428,395 @@ static IntRect getAbsoluteBoundingBox(Node* node) {
else if (render->isText())
rect = toRenderText(render)->linesBoundingBox();
else
- LOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName());
- FloatPoint absPos = render->localToAbsolute();
+ ALOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName());
+ FloatPoint absPos = render->localToAbsolute(FloatPoint(), false, true);
rect.move(absPos.x(), absPos.y());
return rect;
}
+WebCore::Frame* WebViewCore::focusedFrame() const
+{
+ return m_mainFrame->page()->focusController()->focusedOrMainFrame();
+}
+
+VisiblePosition WebViewCore::visiblePositionForContentPoint(int x, int 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
+ | 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;
+
+ return node->renderer()->positionForPoint(result.localPoint());
+}
+
+bool WebViewCore::selectWordAt(int x, int y)
+{
+ HitTestResult hoverResult;
+ moveMouse(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);
+
+ focusedFrame()->document()->renderView()->layer()->hitTest(request, result);
+
+ // Matching the logic in MouseEventWithHitTestResults::targetNode()
+ Node* node = result.innerNode();
+ if (!node)
+ return false;
+ Element* element = node->parentElement();
+ if (!node->inDocument() && element && element->inDocument())
+ node = element;
+
+ SelectionController* sc = focusedFrame()->selection();
+ bool wordSelected = false;
+ 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()));
+ wordSelected = selectWordAroundPosition(node->document()->frame(), pos);
+ }
+ return wordSelected;
+}
+
+bool WebViewCore::selectWordAroundPosition(Frame* frame, VisiblePosition pos)
+{
+ VisibleSelection selection(pos);
+ selection.expandUsingGranularity(WordGranularity);
+ SelectionController* selectionController = frame->selection();
+
+ bool wordSelected = false;
+ if (selectionController->shouldChangeSelection(selection)) {
+ bool allWhitespaces = true;
+ RefPtr<Range> firstRange = selection.firstRange();
+ String text = firstRange.get() ? firstRange->text() : "";
+ for (size_t i = 0; i < text.length(); ++i) {
+ if (!isSpaceOrNewline(text[i])) {
+ allWhitespaces = false;
+ break;
+ }
+ }
+ if (allWhitespaces) {
+ VisibleSelection emptySelection(pos);
+ selectionController->setSelection(emptySelection);
+ } else {
+ selectionController->setSelection(selection);
+ wordSelected = true;
+ }
+ }
+ return wordSelected;
+}
+
+int WebViewCore::platformLayerIdFromNode(Node* node, LayerAndroid** outLayer)
+{
+ if (!node || !node->renderer())
+ return -1;
+ RenderLayer* renderLayer = node->renderer()->enclosingLayer();
+ while (renderLayer && !renderLayer->isComposited())
+ renderLayer = renderLayer->parent();
+ if (!renderLayer || !renderLayer->isComposited())
+ return -1;
+ GraphicsLayer* graphicsLayer = renderLayer->backing()->graphicsLayer();
+ if (!graphicsLayer)
+ return -1;
+ GraphicsLayerAndroid* agl = static_cast<GraphicsLayerAndroid*>(graphicsLayer);
+ LayerAndroid* layer = agl->foregroundLayer();
+ if (!layer)
+ layer = agl->contentLayer();
+ if (!layer)
+ return -1;
+ if (outLayer)
+ *outLayer = layer;
+ return layer->uniqueId();
+}
+
+void WebViewCore::layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& offset)
+{
+ while (layer) {
+ const SkPoint& pos = layer->getPosition();
+ offset.move(pos.fX, pos.fY);
+ const IntPoint& scroll = layer->getScrollOffset();
+ offset.move(-scroll.x(), -scroll.y());
+ layer = static_cast<LayerAndroid*>(layer->getParent());
+ }
+}
+
+void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer,
+ const WebCore::Position& pos, const IntPoint& frameOffset,
+ SelectText::HandleId handleId, int caretRectOffset, EAffinity affinity)
+{
+ Node* node = pos.anchorNode();
+ LayerAndroid* layer = 0;
+ int layerId = platformLayerIdFromNode(node, &layer);
+ selectTextContainer->setCaretLayerId(handleId, layerId);
+ IntPoint offset = frameOffset;
+ layerToAbsoluteOffset(layer, offset);
+ RenderObject* r = node->renderer();
+ RenderText* renderText = toRenderText(r);
+ int caretOffset;
+ InlineBox* inlineBox;
+ pos.getInlineBoxAndOffset(affinity, inlineBox, caretOffset);
+ IntRect caretRect = renderText->localCaretRect(inlineBox, caretOffset);
+ FloatPoint absoluteOffset = renderText->localToAbsolute(caretRect.location());
+ caretRect.setX(absoluteOffset.x() - offset.x() + caretRectOffset);
+ caretRect.setY(absoluteOffset.y() - offset.y());
+ selectTextContainer->setCaretRect(handleId, caretRect);
+ selectTextContainer->setTextRect(handleId,
+ positionToTextRect(pos, affinity, offset));
+}
+
+bool WebViewCore::isLtr(const Position& position)
+{
+ InlineBox* inlineBox = 0;
+ int caretOffset = 0;
+ position.getInlineBoxAndOffset(DOWNSTREAM, inlineBox, caretOffset);
+ bool isLtr;
+ if (inlineBox)
+ isLtr = inlineBox->isLeftToRightDirection();
+ else
+ isLtr = position.primaryDirection() == LTR;
+ return isLtr;
+}
+
+SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
+{
+ bool isCaret = selection.isCaret();
+ if (selection.isNone() || (!selection.isContentEditable() && isCaret)
+ || !selection.start().anchorNode()
+ || !selection.start().anchorNode()->renderer()
+ || !selection.end().anchorNode()
+ || !selection.end().anchorNode()->renderer())
+ return 0;
+
+ RefPtr<Range> range = selection.firstRange();
+ Node* startContainer = range->startContainer();
+ Node* endContainer = range->endContainer();
+
+ if (!startContainer || !endContainer)
+ return 0;
+ if (!isCaret && startContainer == endContainer
+ && range->startOffset() == range->endOffset())
+ return 0;
+
+ IntPoint frameOffset = convertGlobalContentToFrameContent(IntPoint());
+ SelectText* selectTextContainer = new SelectText();
+ if (isCaret) {
+ setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset,
+ SelectText::LeftHandle, 0, selection.affinity());
+ setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset,
+ SelectText::RightHandle, 0, selection.affinity());
+ } else {
+ bool ltr = isLtr(selection.start());
+ Position left = ltr ? selection.start() : selection.end();
+ Position right = ltr ? selection.end() : selection.start();
+ int leftOffset = isLtr(left) ? 0 : -1;
+ int rightOffset = isLtr(right) ? 0 : -1;
+ setSelectionCaretInfo(selectTextContainer, left, frameOffset,
+ SelectText::LeftHandle, leftOffset, selection.affinity());
+ setSelectionCaretInfo(selectTextContainer, right, frameOffset,
+ SelectText::RightHandle, rightOffset, selection.affinity());
+
+ Node* stopNode = range->pastLastNode();
+ for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) {
+ RenderObject* r = node->renderer();
+ if (!r || !r->isText() || r->style()->visibility() != VISIBLE)
+ continue;
+ RenderText* renderText = toRenderText(r);
+ int startOffset = node == startContainer ? range->startOffset() : 0;
+ int endOffset = node == endContainer ? range->endOffset() : numeric_limits<int>::max();
+ LayerAndroid* layer = 0;
+ int layerId = platformLayerIdFromNode(node, &layer);
+ Vector<IntRect> rects;
+ renderText->absoluteRectsForRange(rects, startOffset, endOffset, true);
+ selectTextContainer->addHighlightRegion(layer, rects, frameOffset);
+ }
+ }
+ selectTextContainer->setText(range->text());
+ return selectTextContainer;
+}
+
+IntRect WebViewCore::positionToTextRect(const Position& position,
+ EAffinity affinity, const WebCore::IntPoint& offset)
+{
+ IntRect textRect;
+ InlineBox* inlineBox;
+ int offsetIndex;
+ position.getInlineBoxAndOffset(affinity, inlineBox, offsetIndex);
+ if (inlineBox && inlineBox->isInlineTextBox()) {
+ InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox);
+ RootInlineBox* root = box->root();
+ RenderText* renderText = box->textRenderer();
+ int left = root->logicalLeft();
+ int width = root->logicalWidth();
+ int top = root->selectionTop();
+ int height = root->selectionHeight();
+
+ if (!renderText->style()->isHorizontalWritingMode()) {
+ swap(left, top);
+ swap(width, height);
+ }
+ FloatPoint origin(left, top);
+ FloatPoint absoluteOrigin = renderText->localToAbsolute(origin);
+
+ textRect.setX(absoluteOrigin.x() - offset.x());
+ textRect.setWidth(width);
+ textRect.setY(absoluteOrigin.y() - offset.y());
+ textRect.setHeight(height);
+ }
+ return textRect;
+}
+
+IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point, WebCore::Frame* frame)
+{
+ if (!frame) frame = focusedFrame();
+ IntPoint frameOffset(-m_scrollOffsetX, -m_scrollOffsetY);
+ frameOffset = frame->view()->windowToContents(frameOffset);
+ return IntPoint(point.x() + frameOffset.x(), point.y() + frameOffset.y());
+}
+
+Position WebViewCore::trimSelectionPosition(const Position &start, const Position& stop)
+{
+ int direction = comparePositions(start, stop);
+ if (direction == 0)
+ return start;
+ bool forward = direction < 0;
+ EAffinity affinity = forward ? DOWNSTREAM : UPSTREAM;
+ bool move;
+ Position pos = start;
+ bool movedTooFar = false;
+ do {
+ move = true;
+ Node* node = pos.anchorNode();
+ if (node && node->isTextNode() && node->renderer()) {
+ RenderText *textRenderer = toRenderText(node->renderer());
+ move = !textRenderer->textLength();
+ }
+ if (move) {
+ Position nextPos = forward ? pos.next() : pos.previous();
+ movedTooFar = nextPos.isNull() || pos == nextPos
+ || ((comparePositions(nextPos, stop) < 0) != forward);
+ pos = nextPos;
+ }
+ } while (move && !movedTooFar);
+ if (movedTooFar)
+ pos = stop;
+ return pos;
+}
+
+void WebViewCore::selectText(int startX, int startY, int endX, int 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())
+ return;
+
+ // Ensure startPosition is before endPosition
+ if (comparePositions(startPosition, endPosition) > 0)
+ swap(startPosition, endPosition);
+
+ if (sc->isContentEditable()) {
+ startPosition = sc->selection().visibleStart().honorEditableBoundaryAtOrAfter(startPosition);
+ endPosition = sc->selection().visibleEnd().honorEditableBoundaryAtOrBefore(endPosition);
+ if (startPosition.isNull() || endPosition.isNull()) {
+ return;
+ }
+ }
+
+ // Ensure startPosition is not at end of block
+ if (startPosition != endPosition && isEndOfBlock(startPosition)) {
+ VisiblePosition nextStartPosition(startPosition.next());
+ if (!nextStartPosition.isNull())
+ startPosition = nextStartPosition;
+ }
+ // Ensure endPosition is not at start of block
+ if (startPosition != endPosition && isStartOfBlock(endPosition)) {
+ VisiblePosition prevEndPosition(endPosition.previous());
+ if (!prevEndPosition.isNull())
+ endPosition = prevEndPosition;
+ }
+
+ Position start = startPosition.deepEquivalent();
+ Position end = endPosition.deepEquivalent();
+ start = trimSelectionPosition(start, end);
+ end = trimSelectionPosition(end, start);
+ VisibleSelection selection(start, end);
+ // Only allow changes between caret positions or to text selection.
+ bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret());
+ if (selectChangeAllowed && sc->shouldChangeSelection(selection))
+ sc->setSelection(selection);
+}
+
+bool WebViewCore::nodeIsClickableOrFocusable(Node* node)
+{
+ if (!node)
+ return false;
+ if (node->disabled())
+ return false;
+ if (!node->inDocument())
+ return false;
+ if (!node->renderer() || node->renderer()->style()->visibility() != VISIBLE)
+ return false;
+ return node->supportsFocus()
+ || node->hasEventListeners(eventNames().clickEvent)
+ || node->hasEventListeners(eventNames().mousedownEvent)
+ || node->hasEventListeners(eventNames().mouseupEvent)
+ || node->hasEventListeners(eventNames().mouseoverEvent);
+}
+
// get the highlight rectangles for the touch point (x, y) with the slop
-Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
+AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool doMoveMouse)
{
- Vector<IntRect> rects;
- m_mousePos = IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
+ if (doMoveMouse)
+ moveMouse(x, y, 0, true);
HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(slop, slop));
+ AndroidHitTestResult androidHitResult(this, hitTestResult);
if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
- LOGE("Should not happen: no in document Node found");
- return rects;
+ ALOGE("Should not happen: no in document Node found");
+ return androidHitResult;
}
const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
if (list.isEmpty()) {
- LOGE("Should not happen: no rect-based-test nodes found");
- return rects;
+ ALOGE("Should not happen: no rect-based-test nodes found");
+ return androidHitResult;
}
Frame* frame = hitTestResult.innerNode()->document()->frame();
Vector<TouchNodeData> nodeDataList;
+ if (hitTestResult.innerNode() != hitTestResult.innerNonSharedNode()
+ && hitTestResult.innerNode()->hasTagName(WebCore::HTMLNames::areaTag)) {
+ HTMLAreaElement* area = static_cast<HTMLAreaElement*>(hitTestResult.innerNode());
+ androidHitResult.hitTestResult().setURLElement(area);
+ androidHitResult.highlightRects().append(area->computeRect(
+ hitTestResult.innerNonSharedNode()->renderer()));
+ return androidHitResult;
+ }
ListHashSet<RefPtr<Node> >::const_iterator last = list.end();
for (ListHashSet<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) {
// TODO: it seems reasonable to not search across the frame. Isn't it?
@@ -1708,14 +1826,12 @@ Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
// traverse up the tree to find the first node that needs highlight
bool found = false;
Node* eventNode = it->get();
+ Node* innerNode = eventNode;
while (eventNode) {
RenderObject* render = eventNode->renderer();
if (render && (render->isBody() || render->isRenderView()))
break;
- if (eventNode->supportsFocus()
- || eventNode->hasEventListeners(eventNames().clickEvent)
- || eventNode->hasEventListeners(eventNames().mousedownEvent)
- || eventNode->hasEventListeners(eventNames().mouseupEvent)) {
+ if (nodeIsClickableOrFocusable(eventNode)) {
found = true;
break;
}
@@ -1747,7 +1863,7 @@ Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
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) {
+ if (eventNode == n->mUrlNode) {
found = false;
break;
}
@@ -1788,16 +1904,19 @@ Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
}
if (!found) {
TouchNodeData newNode;
- newNode.mNode = eventNode;
+ newNode.mUrlNode = eventNode;
newNode.mBounds = rect;
+ newNode.mInnerNode = innerNode;
nodeDataList.append(newNode);
}
}
- if (!nodeDataList.size())
- return rects;
+ if (!nodeDataList.size()) {
+ androidHitResult.searchContentDetectors();
+ return androidHitResult;
+ }
// finally select the node with the largest overlap with the fat point
TouchNodeData final;
- final.mNode = 0;
+ final.mUrlNode = 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;
@@ -1806,101 +1925,47 @@ Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
IntRect rect = n->mBounds;
rect.intersect(testRect);
int a = rect.width() * rect.height();
- if (a > area) {
+ if (a > area || !final.mUrlNode) {
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.mUrlNode) {
+ // Update innerNode and innerNonSharedNode
+ androidHitResult.hitTestResult().setInnerNode(final.mInnerNode);
+ androidHitResult.hitTestResult().setInnerNonSharedNode(final.mInnerNode);
+ if (final.mUrlNode->isElementNode()) {
+ // We found a URL element. Update the hitTestResult
+ androidHitResult.setURLElement(static_cast<Element*>(final.mUrlNode));
+ } else {
+ androidHitResult.setURLElement(0);
}
- 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].maxX()) {
- 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].maxY()) {
- if (y - rects[i].maxY() + 1 < distance) {
- newx = x;
- newy = rects[i].maxY() - 1;
- distance = y - rects[i].maxY() + 1;
- }
- }
- } else if (y >= rects[i].y() && y < rects[i].maxY()) {
- 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].maxX()) {
- if (x - rects[i].maxX() + 1 < distance) {
- newx = rects[i].maxX() - 1;
- newy = y;
- distance = x - rects[i].maxX() + 1;
- }
- }
+ Vector<IntRect>& highlightRects = androidHitResult.highlightRects();
+ if (doMoveMouse && highlightRects.size() > 0) {
+ // adjust m_mousePos if it is not inside the returned highlight
+ // rectangles
+ IntRect foundIntersection;
+ IntRect inputRect = IntRect(x - slop, y - slop,
+ slop * 2 + 1, slop * 2 + 1);
+ for (size_t i = 0; i < highlightRects.size(); i++) {
+ IntRect& hr = highlightRects[i];
+ IntRect test = inputRect;
+ test.intersect(hr);
+ if (!test.isEmpty()) {
+ foundIntersection = test;
+ break;
}
}
- 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;
+ if (!foundIntersection.isEmpty() && !foundIntersection.contains(x, y)) {
+ IntPoint pt = foundIntersection.center();
+ moveMouse(pt.x(), pt.y(), 0, true);
}
}
- 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);
- }
+ } else {
+ androidHitResult.searchContentDetectors();
}
- return rects;
+ return androidHitResult;
}
///////////////////////////////////////////////////////////////////////////////
@@ -2071,70 +2136,46 @@ static PluginView* nodeIsPlugin(Node* node) {
return 0;
}
-Node* WebViewCore::cursorNodeIsPlugin() {
- gCursorBoundsMutex.lock();
- bool hasCursorBounds = m_hasCursorBounds;
- Frame* frame = (Frame*) m_cursorFrame;
- Node* node = (Node*) m_cursorNode;
- gCursorBoundsMutex.unlock();
- if (hasCursorBounds && CacheBuilder::validNode(m_mainFrame, frame, node)
- && nodeIsPlugin(node)) {
- return node;
- }
- return 0;
-}
-
///////////////////////////////////////////////////////////////////////////////
-void WebViewCore::moveMouseIfLatest(int moveGeneration,
- WebCore::Frame* frame, int x, int y)
-{
- DBG_NAV_LOGD("m_moveGeneration=%d moveGeneration=%d"
- " frame=%p x=%d y=%d",
- m_moveGeneration, moveGeneration, frame, x, y);
- if (m_moveGeneration > moveGeneration) {
- DBG_NAV_LOGD("m_moveGeneration=%d > moveGeneration=%d",
- m_moveGeneration, moveGeneration);
- return; // short-circuit if a newer move has already been generated
- }
- m_lastGeneration = moveGeneration;
- moveMouse(frame, x, y);
-}
-
-void WebViewCore::moveFocus(WebCore::Frame* frame, WebCore::Node* node)
-{
- DBG_NAV_LOGD("frame=%p node=%p", frame, node);
- if (!node || !CacheBuilder::validNode(m_mainFrame, frame, node)
- || !node->isElementNode())
- return;
- // Code borrowed from FocusController::advanceFocus
- WebCore::FocusController* focusController
- = m_mainFrame->page()->focusController();
- WebCore::Document* oldDoc
- = focusController->focusedOrMainFrame()->document();
- if (oldDoc->focusedNode() == node)
- return;
- if (node->document() != oldDoc)
- oldDoc->setFocusedNode(0);
- focusController->setFocusedFrame(frame);
- static_cast<WebCore::Element*>(node)->focus(false);
-}
// Update mouse position
-void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y)
+void WebViewCore::moveMouse(int x, int y, HitTestResult* hoveredNode, bool isClickCandidate)
{
- DBG_NAV_LOGD("frame=%p x=%d y=%d scrollOffset=(%d,%d)", frame,
- x, y, m_scrollOffsetX, m_scrollOffsetY);
- if (!frame || !CacheBuilder::validNode(m_mainFrame, frame, 0))
- frame = m_mainFrame;
// mouse event expects the position in the window coordinate
m_mousePos = WebCore::IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
+ if (isClickCandidate)
+ m_mouseClickPos = m_mousePos;
// validNode will still return true if the node is null, as long as we have
// a valid frame. Do not want to make a call on frame unless it is valid.
WebCore::PlatformMouseEvent mouseEvent(m_mousePos, m_mousePos,
WebCore::NoButton, WebCore::MouseEventMoved, 1, false, false, false,
false, WTF::currentTime());
- frame->eventHandler()->handleMouseMoveEvent(mouseEvent);
- updateCacheOnNodeChange();
+ m_mainFrame->eventHandler()->handleMouseMoveEvent(mouseEvent, hoveredNode);
+}
+
+Position WebViewCore::getPositionForOffset(Node* node, int offset)
+{
+ 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());
+ iterator.advance(offset);
+ return iterator.range()->startPosition();
+}
+
+void WebViewCore::setSelection(Node* node, int start, int end)
+{
+ RenderTextControl* control = toRenderTextControl(node);
+ if (control)
+ setSelectionRange(node, start, end);
+ else {
+ Position startPosition = getPositionForOffset(node, start);
+ Position endPosition = getPositionForOffset(node, end);
+ VisibleSelection selection(startPosition, endPosition);
+ SelectionController* selector = node->document()->frame()->selection();
+ selector->setSelection(selection);
+ }
}
void WebViewCore::setSelection(int start, int end)
@@ -2142,28 +2183,22 @@ void WebViewCore::setSelection(int start, int end)
WebCore::Node* focus = currentFocus();
if (!focus)
return;
- WebCore::RenderObject* renderer = focus->renderer();
- if (!renderer || (!renderer->isTextField() && !renderer->isTextArea()))
- return;
- if (start > end) {
- int temp = start;
- start = end;
- end = temp;
- }
+ if (start > end)
+ swap(start, end);
+
// Tell our EditorClient that this change was generated from the UI, so it
// does not need to echo it to the UI.
EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
m_mainFrame->editor()->client());
client->setUiGeneratedSelectionChange(true);
- setSelectionRange(focus, start, end);
- if (start != end) {
+ setSelection(focus, start, end);
+ RenderTextControl* control = toRenderTextControl(focus);
+ if (start != end && control) {
// Fire a select event. No event is sent when the selection reduces to
// an insertion point
- RenderTextControl* control = toRenderTextControl(renderer);
control->selectionChanged(true);
}
client->setUiGeneratedSelectionChange(false);
- WebCore::Frame* focusedFrame = focus->document()->frame();
bool isPasswordField = false;
if (focus->isElementNode()) {
WebCore::Element* element = static_cast<WebCore::Element*>(focus);
@@ -2172,7 +2207,7 @@ void WebViewCore::setSelection(int start, int end)
}
// For password fields, this is done in the UI side via
// bringPointIntoView, since the UI does the drawing.
- if (renderer->isTextArea() || !isPasswordField)
+ if ((control && control->isTextArea()) || !isPasswordField)
revealSelection();
}
@@ -2197,7 +2232,7 @@ String WebViewCore::modifySelection(const int direction, const int axis)
case AXIS_DOCUMENT:
return modifySelectionDomNavigationAxis(selection, direction, axis);
default:
- LOGE("Invalid navigation axis: %d", axis);
+ ALOGE("Invalid navigation axis: %d", axis);
return String();
}
}
@@ -2238,9 +2273,9 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
// initialize the selection if necessary
if (selection->rangeCount() == 0) {
if (m_currentNodeDomNavigationAxis
- && CacheBuilder::validNode(m_mainFrame,
+ && validNode(m_mainFrame,
m_mainFrame, m_currentNodeDomNavigationAxis)) {
- PassRefPtr<Range> rangeRef =
+ RefPtr<Range> rangeRef =
selection->frame()->document()->createRange();
rangeRef->selectNode(m_currentNodeDomNavigationAxis, ec);
m_currentNodeDomNavigationAxis = 0;
@@ -2249,15 +2284,6 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
selection->addRange(rangeRef.get());
} else if (currentFocus()) {
selection->setPosition(currentFocus(), 0, ec);
- } else if (m_cursorNode
- && CacheBuilder::validNode(m_mainFrame,
- m_mainFrame, m_cursorNode)) {
- PassRefPtr<Range> rangeRef =
- selection->frame()->document()->createRange();
- rangeRef->selectNode(reinterpret_cast<Node*>(m_cursorNode), ec);
- if (ec)
- return String();
- selection->addRange(rangeRef.get());
} else {
selection->setPosition(body, 0, ec);
}
@@ -2456,13 +2482,13 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
scrollNodeIntoView(m_mainFrame, selection->anchorNode());
// format markup for the visible content
- PassRefPtr<Range> range = selection->getRangeAt(0, ec);
+ RefPtr<Range> range = selection->getRangeAt(0, ec);
if (ec)
return String();
IntRect bounds = range->boundingBox();
selectAt(bounds.center().x(), bounds.center().y());
markup = formatMarkup(selection);
- LOGV("Selection markup: %s", markup.utf8().data());
+ ALOGV("Selection markup: %s", markup.utf8().data());
return markup;
}
@@ -2670,7 +2696,7 @@ String WebViewCore::modifySelectionDomNavigationAxis(DOMSelection* selection, in
if (!m_currentNodeDomNavigationAxis)
m_currentNodeDomNavigationAxis = currentFocus();
if (!m_currentNodeDomNavigationAxis
- || !CacheBuilder::validNode(m_mainFrame, m_mainFrame,
+ || !validNode(m_mainFrame, m_mainFrame,
m_currentNodeDomNavigationAxis))
m_currentNodeDomNavigationAxis = body;
Node* currentNode = m_currentNodeDomNavigationAxis;
@@ -2714,14 +2740,14 @@ String WebViewCore::modifySelectionDomNavigationAxis(DOMSelection* selection, in
if (direction == DIRECTION_FORWARD)
currentNode = currentNode->lastDescendant();
} else {
- LOGE("Invalid axis: %d", axis);
+ ALOGE("Invalid axis: %d", axis);
return String();
}
if (currentNode) {
m_currentNodeDomNavigationAxis = currentNode;
scrollNodeIntoView(m_mainFrame, currentNode);
String selectionString = createMarkup(currentNode);
- LOGV("Selection markup: %s", selectionString.utf8().data());
+ ALOGV("Selection markup: %s", selectionString.utf8().data());
return selectionString;
}
return String();
@@ -2771,7 +2797,7 @@ bool WebViewCore::isVisible(Node* node)
while (currentNode && currentNode != body) {
RenderStyle* style = currentNode->computedStyle();
if (style &&
- (style->display() == NONE || style->visibility() == HIDDEN)) {
+ (style->display() == WebCore::NONE || style->visibility() == WebCore::HIDDEN)) {
return false;
}
currentNode = currentNode->parentNode();
@@ -2783,7 +2809,7 @@ String WebViewCore::formatMarkup(DOMSelection* selection)
{
ExceptionCode ec = 0;
String markup = String();
- PassRefPtr<Range> wholeRange = selection->getRangeAt(0, ec);
+ RefPtr<Range> wholeRange = selection->getRangeAt(0, ec);
if (ec)
return String();
if (!wholeRange->startContainer() || !wholeRange->startContainer())
@@ -2793,7 +2819,7 @@ String WebViewCore::formatMarkup(DOMSelection* selection)
Node* firstNode = wholeRange->firstNode();
Node* pastLastNode = wholeRange->pastLastNode();
Node* currentNode = firstNode;
- PassRefPtr<Range> currentRange;
+ RefPtr<Range> currentRange;
while (currentNode != pastLastNode) {
Node* nextNode = currentNode->traverseNextNode();
@@ -2870,7 +2896,6 @@ void WebViewCore::deleteSelection(int start, int end, int textGeneration)
key(up);
client->setUiGeneratedSelectionChange(false);
m_textGeneration = textGeneration;
- m_shouldPaintCaret = true;
}
void WebViewCore::replaceTextfieldText(int oldStart,
@@ -2886,13 +2911,15 @@ void WebViewCore::replaceTextfieldText(int oldStart,
EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
m_mainFrame->editor()->client());
client->setUiGeneratedSelectionChange(true);
- WebCore::TypingCommand::insertText(focus->document(), replace,
- false);
+ if (replace.length())
+ WebCore::TypingCommand::insertText(focus->document(), replace,
+ false);
+ else
+ WebCore::TypingCommand::deleteSelection(focus->document());
client->setUiGeneratedSelectionChange(false);
// setSelection calls revealSelection, so there is no need to do it here.
setSelection(start, end);
m_textGeneration = textGeneration;
- m_shouldPaintCaret = true;
}
void WebViewCore::passToJs(int generation, const WTF::String& current,
@@ -2900,13 +2927,6 @@ void WebViewCore::passToJs(int generation, const WTF::String& current,
{
WebCore::Node* focus = currentFocus();
if (!focus) {
- DBG_NAV_LOG("!focus");
- clearTextEntry();
- return;
- }
- WebCore::RenderObject* renderer = focus->renderer();
- if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) {
- DBG_NAV_LOGD("renderer==%p || not text", renderer);
clearTextEntry();
return;
}
@@ -2921,42 +2941,36 @@ void WebViewCore::passToJs(int generation, const WTF::String& current,
client->setUiGeneratedSelectionChange(false);
m_blockTextfieldUpdates = false;
m_textGeneration = generation;
- WebCore::RenderTextControl* renderText =
- static_cast<WebCore::RenderTextControl*>(renderer);
- WTF::String test = renderText->text();
+ WTF::String test = getInputText(focus);
if (test != current) {
// If the text changed during the key event, update the UI text field.
updateTextfield(focus, false, test);
- } else {
- DBG_NAV_LOG("test == current");
}
// Now that the selection has settled down, send it.
updateTextSelection();
- m_shouldPaintCaret = true;
}
-void WebViewCore::scrollFocusedTextInput(float xPercent, int y)
+WebCore::IntRect WebViewCore::scrollFocusedTextInput(float xPercent, int y)
{
WebCore::Node* focus = currentFocus();
if (!focus) {
- DBG_NAV_LOG("!focus");
clearTextEntry();
- return;
+ return WebCore::IntRect();
}
- WebCore::RenderObject* renderer = focus->renderer();
- if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) {
- DBG_NAV_LOGD("renderer==%p || not text", renderer);
+ WebCore::RenderTextControl* renderText = toRenderTextControl(focus);
+ if (!renderText) {
clearTextEntry();
- return;
+ return WebCore::IntRect();
}
- WebCore::RenderTextControl* renderText =
- static_cast<WebCore::RenderTextControl*>(renderer);
+
int x = (int) (xPercent * (renderText->scrollWidth() -
renderText->clientWidth()));
- DBG_NAV_LOGD("x=%d y=%d xPercent=%g scrollW=%d clientW=%d", x, y,
- xPercent, renderText->scrollWidth(), renderText->clientWidth());
renderText->setScrollLeft(x);
renderText->setScrollTop(y);
+ focus->document()->frame()->selection()->recomputeCaretRect();
+ LayerAndroid* layer = 0;
+ platformLayerIdFromNode(focus, &layer);
+ return absoluteContentRect(focus, layer);
}
void WebViewCore::setFocusControllerActive(bool active)
@@ -2966,7 +2980,7 @@ void WebViewCore::setFocusControllerActive(bool active)
void WebViewCore::saveDocumentState(WebCore::Frame* frame)
{
- if (!CacheBuilder::validNode(m_mainFrame, frame, 0))
+ if (!validNode(m_mainFrame, frame, 0))
frame = m_mainFrame;
WebCore::HistoryItem *item = frame->loader()->history()->currentItem();
@@ -2982,9 +2996,9 @@ void WebViewCore::saveDocumentState(WebCore::Frame* frame)
static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t count)
{
jclass stringClass = env->FindClass("java/lang/String");
- LOG_ASSERT(stringClass, "Could not find java/lang/String");
+ ALOG_ASSERT(stringClass, "Could not find java/lang/String");
jobjectArray array = env->NewObjectArray(count, stringClass, 0);
- LOG_ASSERT(array, "Could not create new string array");
+ ALOG_ASSERT(array, "Could not create new string array");
for (size_t i = 0; i < count; i++) {
jobject newString = env->NewString(&labels[i][1], labels[i][0]);
@@ -3007,11 +3021,19 @@ void WebViewCore::openFileChooser(PassRefPtr<WebCore::FileChooser> chooser)
return;
WTF::String acceptType = chooser->acceptTypes();
+ WTF::String capture;
+
+#if ENABLE(MEDIA_CAPTURE)
+ capture = chooser->capture();
+#endif
+
jstring jAcceptType = wtfStringToJstring(env, acceptType, true);
+ jstring jCapture = wtfStringToJstring(env, capture, true);
jstring jName = (jstring) env->CallObjectMethod(
- javaObject.get(), m_javaGlue->m_openFileChooser, jAcceptType);
+ javaObject.get(), m_javaGlue->m_openFileChooser, jAcceptType, jCapture);
checkException(env);
env->DeleteLocalRef(jAcceptType);
+ env->DeleteLocalRef(jCapture);
WTF::String wtfString = jstringToWtfString(env, jName);
env->DeleteLocalRef(jName);
@@ -3023,7 +3045,7 @@ void WebViewCore::openFileChooser(PassRefPtr<WebCore::FileChooser> chooser)
void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount,
bool multiple, const int selected[], size_t selectedCountOrSelection)
{
- LOG_ASSERT(m_javaGlue->m_obj, "No java widget associated with this view!");
+ ALOG_ASSERT(m_javaGlue->m_obj, "No java widget associated with this view!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject javaObject = m_javaGlue->object(env);
@@ -3082,14 +3104,15 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event)
{
WebCore::EventHandler* eventHandler;
WebCore::Node* focusNode = currentFocus();
- DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p",
- event.keyIdentifier().utf8().data(), event.unichar(), focusNode);
if (focusNode) {
WebCore::Frame* frame = focusNode->document()->frame();
- 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
@@ -3099,33 +3122,53 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event)
}
return handled;
} else {
- eventHandler = m_mainFrame->eventHandler();
+ eventHandler = focusedFrame()->eventHandler();
}
return eventHandler->keyEvent(event);
}
-// For when the user clicks the trackball, presses dpad center, or types into an
-// unfocused textfield. In the latter case, 'fake' will be true
-void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node, bool fake) {
- if (!node) {
- WebCore::IntPoint pt = m_mousePos;
- pt.move(m_scrollOffsetX, m_scrollOffsetY);
- WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()->
- hitTestResultAtPoint(pt, false);
- node = hitTestResult.innerNode();
- frame = node->document()->frame();
- DBG_NAV_LOGD("m_mousePos=(%d,%d) m_scrollOffset=(%d,%d) pt=(%d,%d)"
- " node=%p", m_mousePos.x(), m_mousePos.y(),
- m_scrollOffsetX, m_scrollOffsetY, pt.x(), pt.y(), node);
- }
- if (node) {
- EditorClientAndroid* client
- = static_cast<EditorClientAndroid*>(
- m_mainFrame->editor()->client());
- client->setShouldChangeSelectedRange(false);
- handleMouseClick(frame, node, fake);
- client->setShouldChangeSelectedRange(true);
+bool WebViewCore::chromeCanTakeFocus(FocusDirection direction)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return false;
+ return env->CallBooleanMethod(javaObject.get(), m_javaGlue->m_chromeCanTakeFocus, direction);
+}
+
+void WebViewCore::chromeTakeFocus(FocusDirection direction)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return;
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_chromeTakeFocus, direction);
+}
+
+void WebViewCore::setInitialFocus(const WebCore::PlatformKeyboardEvent& platformEvent)
+{
+ Frame* frame = focusedFrame();
+ Document* document = frame->document();
+ if (document)
+ document->setFocusedNode(0);
+ FocusDirection direction;
+ switch (platformEvent.nativeVirtualKeyCode()) {
+ case AKEYCODE_DPAD_LEFT:
+ direction = FocusDirectionLeft;
+ break;
+ case AKEYCODE_DPAD_RIGHT:
+ direction = FocusDirectionRight;
+ break;
+ case AKEYCODE_DPAD_UP:
+ direction = FocusDirectionUp;
+ break;
+ default:
+ direction = FocusDirectionDown;
+ break;
}
+ RefPtr<KeyboardEvent> webkitEvent = KeyboardEvent::create(platformEvent, 0);
+ m_mainFrame->page()->focusController()->setInitialFocus(direction,
+ webkitEvent.get());
}
#if USE(ACCELERATED_COMPOSITING)
@@ -3139,9 +3182,9 @@ GraphicsLayerAndroid* WebViewCore::graphicsRootLayer() const
}
#endif
-bool WebViewCore::handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint>& points, int actionIndex, int metaState)
+int WebViewCore::handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint>& points, int actionIndex, int metaState)
{
- bool preventDefault = false;
+ int flags = 0;
#if USE(ACCELERATED_COMPOSITING)
GraphicsLayerAndroid* rootLayer = graphicsRootLayer();
@@ -3182,18 +3225,10 @@ bool WebViewCore::handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint
type = WebCore::TouchEnd;
defaultTouchState = WebCore::PlatformTouchPoint::TouchStationary;
break;
- case 0x100: // WebViewCore.ACTION_LONGPRESS
- type = WebCore::TouchLongPress;
- defaultTouchState = WebCore::PlatformTouchPoint::TouchPressed;
- break;
- case 0x200: // WebViewCore.ACTION_DOUBLETAP
- type = WebCore::TouchDoubleTap;
- defaultTouchState = WebCore::PlatformTouchPoint::TouchPressed;
- break;
default:
// We do not support other kinds of touch event inside WebCore
// at the moment.
- LOGW("Java passed a touch event type that we do not support in WebCore: %d", action);
+ ALOGW("Java passed a touch event type that we do not support in WebCore: %d", action);
return 0;
}
@@ -3213,52 +3248,41 @@ bool WebViewCore::handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint
}
WebCore::PlatformTouchEvent te(ids, points, type, touchStates, metaState);
- preventDefault = m_mainFrame->eventHandler()->handleTouchEvent(te);
+ if (m_mainFrame->eventHandler()->handleTouchEvent(te))
+ flags |= TOUCH_FLAG_PREVENT_DEFAULT;
+ if (te.hitTouchHandler())
+ flags |= TOUCH_FLAG_HIT_HANDLER;
#endif
#if USE(ACCELERATED_COMPOSITING)
if (rootLayer)
rootLayer->pauseDisplay(false);
#endif
- return preventDefault;
+ return flags;
}
-void WebViewCore::touchUp(int touchGeneration,
- WebCore::Frame* frame, WebCore::Node* node, int x, int y)
+bool WebViewCore::performMouseClick()
{
- 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);
- return; // short circuit if a newer touch has been generated
- }
- // This moves m_mousePos to the correct place, and handleMouseClick uses
- // 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();
- }
- DBG_NAV_LOGD("touchGeneration=%d handleMouseClick frame=%p node=%p"
- " x=%d y=%d", touchGeneration, frame, node, x, y);
- handleMouseClick(frame, node, false);
+ WebCore::PlatformMouseEvent mouseDown(m_mouseClickPos, m_mouseClickPos, WebCore::LeftButton,
+ WebCore::MouseEventPressed, 1, false, false, false, false,
+ WTF::currentTime());
+ // ignore the return from as it will return true if the hit point can trigger selection change
+ m_mainFrame->eventHandler()->handleMousePressEvent(mouseDown);
+ WebCore::PlatformMouseEvent mouseUp(m_mouseClickPos, m_mouseClickPos, WebCore::LeftButton,
+ WebCore::MouseEventReleased, 1, false, false, false, false,
+ WTF::currentTime());
+ bool handled = m_mainFrame->eventHandler()->handleMouseReleaseEvent(mouseUp);
+
+ WebCore::Node* focusNode = currentFocus();
+ initializeTextInput(focusNode, false);
+ return handled;
}
// Check for the "x-webkit-soft-keyboard" attribute. If it is there and
// set to hidden, do not show the soft keyboard. Node passed as a parameter
// must not be null.
static bool shouldSuppressKeyboard(const WebCore::Node* node) {
- LOG_ASSERT(node, "node passed to shouldSuppressKeyboard cannot be null");
+ ALOG_ASSERT(node, "node passed to shouldSuppressKeyboard cannot be null");
const NamedNodeMap* attributes = node->attributes();
if (!attributes) return false;
size_t length = attributes->length();
@@ -3270,84 +3294,160 @@ static bool shouldSuppressKeyboard(const WebCore::Node* node) {
return false;
}
-// Common code for both clicking with the trackball and touchUp
-// Also used when typing into a non-focused textfield to give the textfield focus,
-// in which case, 'fake' is set to true
-bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr, bool fake)
-{
- bool valid = !framePtr || CacheBuilder::validNode(m_mainFrame, framePtr, nodePtr);
- WebFrame* webFrame = WebFrame::getWebFrame(m_mainFrame);
- if (valid && nodePtr) {
- // Need to special case area tags because an image map could have an area element in the middle
- // so when attempting to get the default, the point chosen would be follow the wrong link.
- if (nodePtr->hasTagName(WebCore::HTMLNames::areaTag)) {
- webFrame->setUserInitiatedAction(true);
- nodePtr->dispatchSimulatedClick(0, true, true);
- webFrame->setUserInitiatedAction(false);
- DBG_NAV_LOG("area");
- return true;
- }
+WebViewCore::InputType WebViewCore::getInputType(Node* node)
+{
+ WebCore::RenderObject* renderer = node->renderer();
+ if (!renderer)
+ return WebViewCore::NONE;
+ if (renderer->isTextArea())
+ return WebViewCore::TEXT_AREA;
+
+ if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
+ HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
+ if (htmlInput->isPasswordField())
+ return WebViewCore::PASSWORD;
+ if (htmlInput->isSearchField())
+ return WebViewCore::SEARCH;
+ if (htmlInput->isEmailField())
+ return WebViewCore::EMAIL;
+ if (htmlInput->isNumberField())
+ return WebViewCore::NUMBER;
+ if (htmlInput->isTelephoneField())
+ return WebViewCore::TELEPHONE;
+ if (htmlInput->isTextField())
+ return WebViewCore::NORMAL_TEXT_FIELD;
}
- if (!valid || !framePtr)
- framePtr = m_mainFrame;
- webFrame->setUserInitiatedAction(true);
- WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton,
- WebCore::MouseEventPressed, 1, false, false, false, false,
- WTF::currentTime());
- // ignore the return from as it will return true if the hit point can trigger selection change
- framePtr->eventHandler()->handleMousePressEvent(mouseDown);
- WebCore::PlatformMouseEvent mouseUp(m_mousePos, m_mousePos, WebCore::LeftButton,
- WebCore::MouseEventReleased, 1, false, false, false, false,
- WTF::currentTime());
- bool handled = framePtr->eventHandler()->handleMouseReleaseEvent(mouseUp);
- webFrame->setUserInitiatedAction(false);
- // If the user clicked on a textfield, make the focusController active
- // so we show the blinking cursor.
- WebCore::Node* focusNode = currentFocus();
- DBG_NAV_LOGD("m_mousePos={%d,%d} focusNode=%p handled=%s", m_mousePos.x(),
- m_mousePos.y(), focusNode, handled ? "true" : "false");
- if (focusNode) {
- WebCore::RenderObject* renderer = focusNode->renderer();
- if (renderer && (renderer->isTextField() || renderer->isTextArea())) {
- bool ime = !shouldSuppressKeyboard(focusNode)
- && !(static_cast<WebCore::HTMLInputElement*>(focusNode))->readOnly();
- if (ime) {
-#if ENABLE(WEB_AUTOFILL)
- if (renderer->isTextField()) {
- EditorClientAndroid* editorC = static_cast<EditorClientAndroid*>(framePtr->page()->editorClient());
- WebAutofill* autoFill = editorC->getAutofill();
- autoFill->formFieldFocused(static_cast<HTMLFormControlElement*>(focusNode));
- }
-#endif
- if (!fake) {
- RenderTextControl* rtc
- = static_cast<RenderTextControl*> (renderer);
- // Force an update of the navcache as this will fire off a
- // message to WebView that *must* have an updated focus.
- m_frameCacheOutOfDate = true;
- updateFrameCache();
- requestKeyboardWithSelection(focusNode, rtc->selectionStart(),
- rtc->selectionEnd());
- }
- } else if (!fake) {
- requestKeyboard(false);
- }
- } else if (!fake){
- // If the selection is contentEditable, show the keyboard so the
- // user can type. Otherwise hide the keyboard because no text
- // input is needed.
- if (isContentEditable(focusNode)) {
- requestKeyboard(true);
- } else if (!nodeIsPlugin(focusNode)) {
- clearTextEntry();
- }
+ if (node->isContentEditable())
+ return WebViewCore::TEXT_AREA;
+
+ return WebViewCore::NONE;
+}
+
+int WebViewCore::getMaxLength(Node* node)
+{
+ int maxLength = -1;
+ if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
+ HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
+ maxLength = htmlInput->maxLength();
+ }
+ return maxLength;
+}
+
+String WebViewCore::getFieldName(Node* node)
+{
+ String name;
+ if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
+ HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
+ name = htmlInput->name();
+ }
+ return name;
+}
+
+bool WebViewCore::isSpellCheckEnabled(Node* node)
+{
+ bool isEnabled = true;
+ if (node->isElementNode()) {
+ WebCore::Element* element = static_cast<WebCore::Element*>(node);
+ isEnabled = element->isSpellCheckingEnabled();
+ }
+ return isEnabled;
+}
+
+bool WebViewCore::isAutoCompleteEnabled(Node* node)
+{
+ bool isEnabled = false;
+ if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
+ HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
+ isEnabled = htmlInput->autoComplete();
+ }
+ return isEnabled;
+}
+
+WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node,
+ LayerAndroid* layer)
+{
+ IntRect contentRect;
+ if (node) {
+ RenderObject* render = node->renderer();
+ if (render && render->isBox() && !render->isBody()) {
+ IntPoint offset = convertGlobalContentToFrameContent(IntPoint(),
+ node->document()->frame());
+ WebViewCore::layerToAbsoluteOffset(layer, offset);
+
+ RenderBox* renderBox = toRenderBox(render);
+ contentRect = renderBox->absoluteContentBox();
+ contentRect.move(-offset.x(), -offset.y());
}
- } else if (!fake) {
- // There is no focusNode, so the keyboard is not needed.
- clearTextEntry();
}
- return handled;
+ return contentRect;
+}
+
+jobject WebViewCore::createTextFieldInitData(Node* node)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ TextFieldInitDataGlue* classDef = m_textFieldInitDataGlue;
+ ScopedLocalRef<jclass> clazz(env,
+ env->FindClass("android/webkit/WebViewCore$TextFieldInitData"));
+ jobject initData = env->NewObject(clazz.get(), classDef->m_constructor);
+ env->SetIntField(initData, classDef->m_fieldPointer,
+ reinterpret_cast<int>(node));
+ ScopedLocalRef<jstring> inputText(env,
+ wtfStringToJstring(env, getInputText(node), true));
+ env->SetObjectField(initData, classDef->m_text, inputText.get());
+ env->SetIntField(initData, classDef->m_type, getInputType(node));
+ env->SetBooleanField(initData, classDef->m_isSpellCheckEnabled,
+ isSpellCheckEnabled(node));
+ Document* document = node->document();
+ PlatformKeyboardEvent tab(AKEYCODE_TAB, 0, 0, false, false, false, false);
+ PassRefPtr<KeyboardEvent> tabEvent =
+ KeyboardEvent::create(tab, document->defaultView());
+ env->SetBooleanField(initData, classDef->m_isTextFieldNext,
+ isTextInput(document->nextFocusableNode(node, tabEvent.get())));
+ env->SetBooleanField(initData, classDef->m_isTextFieldPrev,
+ isTextInput(document->previousFocusableNode(node, tabEvent.get())));
+ env->SetBooleanField(initData, classDef->m_isAutoCompleteEnabled,
+ isAutoCompleteEnabled(node));
+ ScopedLocalRef<jstring> fieldName(env,
+ wtfStringToJstring(env, getFieldName(node), false));
+ env->SetObjectField(initData, classDef->m_name, fieldName.get());
+ ScopedLocalRef<jstring> label(env,
+ wtfStringToJstring(env, requestLabel(document->frame(), node), false));
+ env->SetObjectField(initData, classDef->m_label, label.get());
+ env->SetIntField(initData, classDef->m_maxLength, getMaxLength(node));
+ LayerAndroid* layer = 0;
+ int layerId = platformLayerIdFromNode(node, &layer);
+ IntRect bounds = absoluteContentRect(node, layer);
+ ScopedLocalRef<jobject> jbounds(env, intRectToRect(env, bounds));
+ env->SetObjectField(initData, classDef->m_contentBounds, jbounds.get());
+ env->SetIntField(initData, classDef->m_nodeLayerId, layerId);
+ IntRect contentRect;
+ RenderTextControl* rtc = toRenderTextControl(node);
+ if (rtc) {
+ contentRect.setWidth(rtc->scrollWidth());
+ contentRect.setHeight(rtc->scrollHeight());
+ contentRect.move(-rtc->scrollLeft(), -rtc->scrollTop());
+ }
+ ScopedLocalRef<jobject> jcontentRect(env, intRectToRect(env, contentRect));
+ env->SetObjectField(initData, classDef->m_contentRect, jcontentRect.get());
+ return initData;
+}
+
+void WebViewCore::initEditField(Node* node)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return;
+ m_textGeneration = 0;
+ int start = 0;
+ int end = 0;
+ getSelectionOffsets(node, start, end);
+ SelectText* selectText = createSelectText(focusedFrame()->selection()->selection());
+ ScopedLocalRef<jobject> initData(env, createTextFieldInitData(node));
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_initEditField,
+ start, end, reinterpret_cast<int>(selectText), initData.get());
+ checkException(env);
}
void WebViewCore::popupReply(int index)
@@ -3368,28 +3468,99 @@ void WebViewCore::popupReply(const int* array, int count)
}
}
-void WebViewCore::formDidBlur(const WebCore::Node* node)
+// This is a slightly modified Node::nextNodeConsideringAtomicNodes() with the
+// extra constraint of limiting the search to inside a containing parent
+WebCore::Node* nextNodeWithinParent(WebCore::Node* parent, WebCore::Node* start)
{
- // If the blur is on a text input, keep track of the node so we can
- // hide the soft keyboard when the new focus is set, if it is not a
- // text input.
- if (isTextInput(node))
- m_blurringNodePointer = reinterpret_cast<int>(node);
+ if (!isAtomicNode(start) && start->firstChild())
+ return start->firstChild();
+ if (start->nextSibling())
+ return start->nextSibling();
+ const Node *n = start;
+ while (n && !n->nextSibling()) {
+ n = n->parentNode();
+ if (n == parent)
+ return 0;
+ }
+ if (n)
+ return n->nextSibling();
+ return 0;
}
-void WebViewCore::focusNodeChanged(const WebCore::Node* newFocus)
+void WebViewCore::initializeTextInput(WebCore::Node* node, bool fake)
{
+ if (node) {
+ if (isTextInput(node)) {
+ bool showKeyboard = true;
+ initEditField(node);
+ WebCore::RenderTextControl* rtc = toRenderTextControl(node);
+ if (rtc && node->hasTagName(HTMLNames::inputTag)) {
+ HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node);
+ bool ime = !shouldSuppressKeyboard(node) && !inputElement->readOnly();
+ if (ime) {
+#if ENABLE(WEB_AUTOFILL)
+ if (rtc->isTextField()) {
+ Page* page = node->document()->page();
+ EditorClient* editorClient = page->editorClient();
+ EditorClientAndroid* androidEditor =
+ static_cast<EditorClientAndroid*>(editorClient);
+ WebAutofill* autoFill = androidEditor->getAutofill();
+ autoFill->formFieldFocused(inputElement);
+ }
+#endif
+ } else
+ showKeyboard = false;
+ }
+ if (!fake)
+ requestKeyboard(showKeyboard);
+ } else if (!fake && !nodeIsPlugin(node)) {
+ // not a text entry field, put away the keyboard.
+ clearTextEntry();
+ }
+ } else if (!fake) {
+ // There is no focusNode, so the keyboard is not needed.
+ clearTextEntry();
+ }
+}
+
+void WebViewCore::focusNodeChanged(WebCore::Node* newFocus)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return;
if (isTextInput(newFocus))
- m_shouldPaintCaret = true;
- else if (m_blurringNodePointer) {
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- AutoJObject javaObject = m_javaGlue->object(env);
- if (!javaObject.get())
- return;
- env->CallVoidMethod(javaObject.get(), m_javaGlue->m_formDidBlur, m_blurringNodePointer);
- checkException(env);
- m_blurringNodePointer = 0;
+ initializeTextInput(newFocus, true);
+ HitTestResult focusHitResult;
+ focusHitResult.setInnerNode(newFocus);
+ focusHitResult.setInnerNonSharedNode(newFocus);
+ if (newFocus && newFocus->isLink() && newFocus->isElementNode()) {
+ focusHitResult.setURLElement(static_cast<Element*>(newFocus));
+ if (newFocus->hasChildNodes() && !newFocus->hasTagName(HTMLNames::imgTag)) {
+ // Check to see if any of the children are images, and if so
+ // set them as the innerNode and innerNonSharedNode
+ // This will stop when it hits the first image. I'm not sure what
+ // should be done in the case of multiple images inside one anchor...
+ Node* nextNode = newFocus->firstChild();
+ bool found = false;
+ while (nextNode) {
+ if (nextNode->hasTagName(HTMLNames::imgTag)) {
+ found = true;
+ break;
+ }
+ nextNode = nextNodeWithinParent(newFocus, nextNode);
+ }
+ if (found) {
+ focusHitResult.setInnerNode(nextNode);
+ focusHitResult.setInnerNonSharedNode(nextNode);
+ }
+ }
}
+ AndroidHitTestResult androidHitTest(this, focusHitResult);
+ jobject jHitTestObj = androidHitTest.createJavaObject(env);
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_focusNodeChanged,
+ reinterpret_cast<int>(newFocus), jHitTestObj);
+ env->DeleteLocalRef(jHitTestObj);
}
void WebViewCore::addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID, int msgLevel) {
@@ -3588,7 +3759,57 @@ WebViewCore::getWebViewJavaObject()
AutoJObject javaObject = m_javaGlue->object(env);
if (!javaObject.get())
return 0;
- return env->GetObjectField(javaObject.get(), gWebViewCoreFields.m_webView);
+ return env->CallObjectMethod(javaObject.get(), m_javaGlue->m_getWebView);
+}
+
+RenderTextControl* WebViewCore::toRenderTextControl(Node* node)
+{
+ RenderTextControl* rtc = 0;
+ RenderObject* renderer = node->renderer();
+ if (renderer && renderer->isTextControl()) {
+ rtc = WebCore::toRenderTextControl(renderer);
+ }
+ return rtc;
+}
+
+void WebViewCore::getSelectionOffsets(Node* node, int& start, int& end)
+{
+ RenderTextControl* rtc = toRenderTextControl(node);
+ if (rtc) {
+ start = rtc->selectionStart();
+ end = rtc->selectionEnd();
+ } else {
+ // It must be content editable field.
+ Document* document = node->document();
+ Frame* frame = document->frame();
+ SelectionController* selector = frame->selection();
+ Position selectionStart = selector->start();
+ Position selectionEnd = selector->end();
+ Position startOfNode = firstPositionInNode(node);
+ RefPtr<Range> startRange = Range::create(document, startOfNode,
+ selectionStart);
+ start = TextIterator::rangeLength(startRange.get(), true);
+ RefPtr<Range> endRange = Range::create(document, startOfNode,
+ selectionEnd);
+ end = TextIterator::rangeLength(endRange.get(), true);
+ }
+}
+
+String WebViewCore::getInputText(Node* node)
+{
+ String text;
+ WebCore::RenderTextControl* renderText = toRenderTextControl(node);
+ if (renderText)
+ text = renderText->text();
+ else {
+ // It must be content editable field.
+ Position start = firstPositionInNode(node);
+ Position end = lastPositionInNode(node);
+ VisibleSelection allEditableText(start, end);
+ if (allEditableText.isRange())
+ text = allEditableText.firstRange()->text();
+ }
+ return text;
}
void WebViewCore::updateTextSelection()
@@ -3597,16 +3818,33 @@ void WebViewCore::updateTextSelection()
AutoJObject javaObject = m_javaGlue->object(env);
if (!javaObject.get())
return;
- WebCore::Node* focusNode = currentFocus();
- if (!focusNode)
+ VisibleSelection selection = focusedFrame()->selection()->selection();
+ int start = 0;
+ int end = 0;
+ if (selection.isCaretOrRange())
+ getSelectionOffsets(selection.start().anchorNode(), start, end);
+ SelectText* selectText = createSelectText(selection);
+ env->CallVoidMethod(javaObject.get(),
+ m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(currentFocus()),
+ start, end, m_textGeneration, reinterpret_cast<int>(selectText));
+ checkException(env);
+}
+
+void WebViewCore::updateTextSizeAndScroll(WebCore::Node* node)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
return;
- RenderObject* renderer = focusNode->renderer();
- if (!renderer || (!renderer->isTextArea() && !renderer->isTextField()))
+ RenderTextControl* rtc = toRenderTextControl(node);
+ if (!rtc)
return;
- RenderTextControl* rtc = static_cast<RenderTextControl*>(renderer);
- env->CallVoidMethod(javaObject.get(),
- m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode),
- rtc->selectionStart(), rtc->selectionEnd(), m_textGeneration);
+ int width = rtc->scrollWidth();
+ int height = rtc->contentHeight();
+ int scrollX = rtc->scrollLeft();
+ int scrollY = rtc->scrollTop();
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateTextSizeAndScroll,
+ reinterpret_cast<int>(node), width, height, scrollX, scrollY);
checkException(env);
}
@@ -3650,11 +3888,18 @@ void WebViewCore::setBackgroundColor(SkColor c)
// need (int) cast to find the right constructor
WebCore::Color bcolor((int)SkColorGetR(c), (int)SkColorGetG(c),
(int)SkColorGetB(c), (int)SkColorGetA(c));
+
+ if (view->baseBackgroundColor() == bcolor)
+ return;
+
view->setBaseBackgroundColor(bcolor);
// Background color of 0 indicates we want a transparent background
if (c == 0)
view->setTransparent(true);
+
+ //invalidate so the new color is shown
+ contentInvalidateAll();
}
jclass WebViewCore::getPluginClass(const WTF::String& libName, const char* className)
@@ -3780,21 +4025,6 @@ void WebViewCore::keepScreenOn(bool screenOn) {
m_screenOnCounter--;
}
-bool WebViewCore::validNodeAndBounds(Frame* frame, Node* node,
- const IntRect& originalAbsoluteBounds)
-{
- bool valid = CacheBuilder::validNode(m_mainFrame, frame, node);
- if (!valid)
- return false;
- RenderObject* renderer = node->renderer();
- if (!renderer)
- return false;
- IntRect absBounds = node->hasTagName(HTMLNames::areaTag)
- ? CacheBuilder::getAreaRect(static_cast<HTMLAreaElement*>(node))
- : renderer->absoluteBoundingBoxRect();
- return absBounds == originalAbsoluteBounds;
-}
-
void WebViewCore::showRect(int left, int top, int width, int height,
int contentWidth, int contentHeight, float xPercentInDoc,
float xPercentInView, float yPercentInDoc, float yPercentInView)
@@ -3848,6 +4078,20 @@ void WebViewCore::enterFullscreenForVideoLayer(int layerId, const WTF::String& u
return;
jstring jUrlStr = wtfStringToJstring(env, url);
env->CallVoidMethod(javaObject.get(), m_javaGlue->m_enterFullscreenForVideoLayer, layerId, jUrlStr);
+ m_fullscreenVideoMode = true;
+ checkException(env);
+}
+
+void WebViewCore::exitFullscreenVideo()
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue->object(env);
+ if (!javaObject.get())
+ return;
+ if (m_fullscreenVideoMode) {
+ env->CallVoidMethod(javaObject.get(), m_javaGlue->m_exitFullscreenVideo);
+ m_fullscreenVideoMode = false;
+ }
checkException(env);
}
#endif
@@ -3873,7 +4117,6 @@ bool WebViewCore::drawIsPaused() const
return false;
}
-#if USE(CHROME_NETWORK_STACK)
void WebViewCore::setWebRequestContextUserAgent()
{
// We cannot create a WebRequestContext, because we might not know it this is a private tab or not yet
@@ -3901,7 +4144,6 @@ WebRequestContext* WebViewCore::webRequestContext()
}
return m_webRequestContext.get();
}
-#endif
void WebViewCore::scrollRenderLayer(int layer, const SkRect& rect)
{
@@ -3922,189 +4164,370 @@ void WebViewCore::scrollRenderLayer(int layer, const SkRect& rect)
if (!owner)
return;
- if (owner->stackingContext())
+ if (owner->isRootLayer()) {
+ FrameView* view = owner->renderer()->frame()->view();
+ IntPoint pt(rect.fLeft, rect.fTop);
+ view->setScrollPosition(pt);
+ } else
owner->scrollToOffset(rect.fLeft, rect.fTop);
#endif
}
+Vector<VisibleSelection> WebViewCore::getTextRanges(
+ int startX, int startY, int endX, int endY)
+{
+ // These are the positions of the selection handles,
+ // which reside below the line that they are selecting.
+ // Use the vertical position higher, which will include
+ // the selected text.
+ startY--;
+ endY--;
+ VisiblePosition startSelect = visiblePositionForContentPoint(startX, startY);
+ VisiblePosition endSelect = visiblePositionForContentPoint(endX, endY);
+ Position start = startSelect.deepEquivalent();
+ Position end = endSelect.deepEquivalent();
+ Vector<VisibleSelection> ranges;
+ if (!start.isNull() && !end.isNull()) {
+ if (comparePositions(start, end) > 0) {
+ swap(start, end); // RTL start/end positions may be swapped
+ }
+ Position nextRangeStart = start;
+ Position previousRangeEnd;
+ do {
+ VisibleSelection selection(nextRangeStart, end);
+ ranges.append(selection);
+ previousRangeEnd = selection.end();
+ nextRangeStart = nextCandidate(previousRangeEnd);
+ } while (comparePositions(previousRangeEnd, end) < 0);
+ }
+ return ranges;
+}
+
+void WebViewCore::deleteText(int startX, int startY, int endX, int endY)
+{
+ Vector<VisibleSelection> ranges =
+ getTextRanges(startX, startY, endX, endY);
+
+ EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setUiGeneratedSelectionChange(true);
+
+ SelectionController* selector = m_mainFrame->selection();
+ for (size_t i = 0; i < ranges.size(); i++) {
+ const VisibleSelection& selection = ranges[i];
+ if (selection.isContentEditable()) {
+ selector->setSelection(selection, CharacterGranularity);
+ Document* document = selection.start().anchorNode()->document();
+ WebCore::TypingCommand::deleteSelection(document, 0);
+ }
+ }
+ client->setUiGeneratedSelectionChange(false);
+}
+
+void WebViewCore::insertText(const WTF::String &text)
+{
+ WebCore::Node* focus = currentFocus();
+ if (!focus || !isTextInput(focus))
+ return;
+
+ Document* document = focus->document();
+
+ EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ if (!client)
+ return;
+ client->setUiGeneratedSelectionChange(true);
+ WebCore::TypingCommand::insertText(document, text,
+ TypingCommand::PreventSpellChecking);
+ client->setUiGeneratedSelectionChange(false);
+}
+
+void WebViewCore::resetFindOnPage()
+{
+ m_searchText.truncate(0);
+ m_matchCount = 0;
+ m_activeMatchIndex = 0;
+ m_activeMatch = 0;
+}
+
+int WebViewCore::findTextOnPage(const WTF::String &text)
+{
+ resetFindOnPage(); // reset even if parameters are bad
+
+ WebCore::Frame* frame = m_mainFrame;
+ if (!frame)
+ return 0;
+
+ m_searchText = text;
+ FindOptions findOptions = WebCore::CaseInsensitive;
+
+ do {
+ frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
+ m_matchCount += frame->editor()->countMatchesForText(text, findOptions,
+ 0, true);
+ frame->editor()->setMarkedTextMatchesAreHighlighted(true);
+ frame = frame->tree()->traverseNextWithWrap(false);
+ } while (frame);
+ m_activeMatchIndex = m_matchCount - 1; // prime first findNext
+ return m_matchCount;
+}
+
+int WebViewCore::findNextOnPage(bool forward)
+{
+ if (!m_mainFrame)
+ return -1;
+ if (!m_matchCount)
+ return -1;
+
+ EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setUiGeneratedSelectionChange(true);
+
+ // Clear previous active match.
+ if (m_activeMatch) {
+ m_mainFrame->document()->markers()->setMarkersActive(
+ m_activeMatch.get(), false);
+ }
+
+ FindOptions findOptions = WebCore::CaseInsensitive
+ | WebCore::StartInSelection | WebCore::WrapAround;
+ if (!forward)
+ findOptions |= WebCore::Backwards;
+
+ // Start from the previous active match.
+ if (m_activeMatch) {
+ m_mainFrame->selection()->setSelection(m_activeMatch.get());
+ }
+
+ bool found = m_mainFrame->editor()->findString(m_searchText, findOptions);
+ if (found) {
+ VisibleSelection selection(m_mainFrame->selection()->selection());
+ if (selection.isNone() || selection.start() == selection.end()) {
+ // Temporary workaround for findString() refusing to select text
+ // marked "-webkit-user-select: none".
+ m_activeMatchIndex = 0;
+ m_activeMatch = 0;
+ } else {
+ // Mark current match "active".
+ if (forward) {
+ ++m_activeMatchIndex;
+ if (m_activeMatchIndex == m_matchCount)
+ m_activeMatchIndex = 0;
+ } else {
+ if (m_activeMatchIndex == 0)
+ m_activeMatchIndex = m_matchCount;
+ --m_activeMatchIndex;
+ }
+ m_activeMatch = selection.firstRange();
+ m_mainFrame->document()->markers()->setMarkersActive(
+ m_activeMatch.get(), true);
+ m_mainFrame->selection()->revealSelection(
+ ScrollAlignment::alignCenterIfNeeded, true);
+ }
+ }
+
+ // Clear selection so it doesn't display.
+ m_mainFrame->selection()->clear();
+ client->setUiGeneratedSelectionChange(false);
+ return m_activeMatchIndex;
+}
+
+String WebViewCore::getText(int startX, int startY, int endX, int endY)
+{
+ String text;
+
+ Vector<VisibleSelection> ranges =
+ getTextRanges(startX, startY, endX, endY);
+
+ for (size_t i = 0; i < ranges.size(); i++) {
+ const VisibleSelection& selection = ranges[i];
+ if (selection.isRange()) {
+ PassRefPtr<Range> range = selection.firstRange();
+ String textInRange = range->text();
+ if (textInRange.length() > 0) {
+ if (text.length() > 0)
+ text.append('\n');
+ text.append(textInRange);
+ }
+ }
+ }
+
+ return text;
+}
+
+/**
+ * Read the persistent locale.
+ */
+void WebViewCore::getLocale(String& language, String& region)
+{
+ char propLang[PROPERTY_VALUE_MAX], propRegn[PROPERTY_VALUE_MAX];
+
+ property_get("persist.sys.language", propLang, "");
+ property_get("persist.sys.country", propRegn, "");
+ if (*propLang == 0 && *propRegn == 0) {
+ /* Set to ro properties, default is en_US */
+ property_get("ro.product.locale.language", propLang, "en");
+ property_get("ro.product.locale.region", propRegn, "US");
+ }
+ language = String(propLang, 2);
+ region = String(propRegn, 2);
+}
+
+void WebViewCore::updateLocale()
+{
+ static String prevLang;
+ static String prevRegn;
+ String language;
+ String region;
+
+ getLocale(language, region);
+
+ if ((language != prevLang) || (region != prevRegn)) {
+ prevLang = language;
+ prevRegn = region;
+ GlyphPageTreeNode::resetRoots();
+ fontCache()->invalidate();
+ }
+}
+
//----------------------------------------------------------------------
// Native JNI methods
//----------------------------------------------------------------------
-static void RevealSelection(JNIEnv *env, jobject obj)
+static void RevealSelection(JNIEnv* env, jobject obj, jint nativeClass)
{
- GET_NATIVE_VIEW(env, obj)->revealSelection();
+ reinterpret_cast<WebViewCore*>(nativeClass)->revealSelection();
}
-static jstring RequestLabel(JNIEnv *env, jobject obj, int framePointer,
- int nodePointer)
+static jstring RequestLabel(JNIEnv* env, jobject obj, jint nativeClass,
+ int framePointer, int nodePointer)
{
- return wtfStringToJstring(env, GET_NATIVE_VIEW(env, obj)->requestLabel(
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ return wtfStringToJstring(env, viewImpl->requestLabel(
(WebCore::Frame*) framePointer, (WebCore::Node*) nodePointer));
}
-static void ClearContent(JNIEnv *env, jobject obj)
+static void ClearContent(JNIEnv* env, jobject obj, jint nativeClass)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
viewImpl->clearContent();
}
-static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj)
-{
- GET_NATIVE_VIEW(env, obj)->updateFrameCacheIfLoading();
-}
-
-static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
- jint textWrapWidth, jfloat scale, jint screenWidth, jint screenHeight,
- jint anchorX, jint anchorY, jboolean ignoreHeight)
+static void SetSize(JNIEnv* env, jobject obj, jint nativeClass, jint width,
+ jint height, jint textWrapWidth, jfloat scale, jint screenWidth,
+ jint screenHeight, jint anchorX, jint anchorY, jboolean ignoreHeight)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- 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");
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize");
viewImpl->setSizeScreenWidthAndScale(width, height, textWrapWidth, scale,
screenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
}
-static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jboolean sendScrollEvent, jint x, jint y)
+static void SetScrollOffset(JNIEnv* env, jobject obj, jint nativeClass,
+ jboolean sendScrollEvent, jint x, jint y)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "need viewImpl");
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "need viewImpl");
- viewImpl->setScrollOffset(gen, sendScrollEvent, x, y);
+ viewImpl->setScrollOffset(sendScrollEvent, x, y);
}
-static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h,
- jint v)
+static void SetGlobalBounds(JNIEnv* env, jobject obj, jint nativeClass,
+ jint x, jint y, jint h, jint v)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "need viewImpl");
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "need viewImpl");
viewImpl->setGlobalBounds(x, y, h, v);
}
-static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar,
- jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isSym,
- jboolean isDown)
+static jboolean Key(JNIEnv* env, jobject obj, jint nativeClass, jint keyCode,
+ jint unichar, jint repeatCount, jboolean isShift, jboolean isAlt,
+ jboolean isSym, jboolean isDown)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- return GET_NATIVE_VIEW(env, obj)->key(PlatformKeyboardEvent(keyCode,
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ return viewImpl->key(PlatformKeyboardEvent(keyCode,
unichar, repeatCount, isDown, isShift, isAlt, isSym));
}
-static void Click(JNIEnv *env, jobject obj, int framePtr, int nodePtr, jboolean fake)
+static void SetInitialFocus(JNIEnv* env, jobject obj, jint nativeClass,
+ jint keyDirection)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in Click");
-
- viewImpl->click(reinterpret_cast<WebCore::Frame*>(framePtr),
- reinterpret_cast<WebCore::Node*>(nodePtr), fake);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ viewImpl->setInitialFocus(PlatformKeyboardEvent(keyDirection,
+ 0, 0, false, false, false, false));
}
-static void ContentInvalidateAll(JNIEnv *env, jobject obj)
+static void ContentInvalidateAll(JNIEnv* env, jobject obj, jint nativeClass)
{
- GET_NATIVE_VIEW(env, obj)->contentInvalidateAll();
+ reinterpret_cast<WebViewCore*>(nativeClass)->contentInvalidateAll();
}
-static void DeleteSelection(JNIEnv *env, jobject obj, jint start, jint end,
- jint textGeneration)
+static void DeleteSelection(JNIEnv* env, jobject obj, jint nativeClass,
+ jint start, jint end, jint textGeneration)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
viewImpl->deleteSelection(start, end, textGeneration);
}
-static void SetSelection(JNIEnv *env, jobject obj, jint start, jint end)
+static void SetSelection(JNIEnv* env, jobject obj, jint nativeClass,
+ jint start, jint end)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
viewImpl->setSelection(start, end);
}
-static jstring ModifySelection(JNIEnv *env, jobject obj, jint direction, jint granularity)
+static jstring ModifySelection(JNIEnv* env, jobject obj, jint nativeClass,
+ jint direction, jint granularity)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
String selectionString = viewImpl->modifySelection(direction, granularity);
return wtfStringToJstring(env, selectionString);
}
-static void ReplaceTextfieldText(JNIEnv *env, jobject obj,
+static void ReplaceTextfieldText(JNIEnv* env, jobject obj, jint nativeClass,
jint oldStart, jint oldEnd, jstring replace, jint start, jint end,
jint textGeneration)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
WTF::String webcoreString = jstringToWtfString(env, replace);
viewImpl->replaceTextfieldText(oldStart,
oldEnd, webcoreString, start, end, textGeneration);
}
-static void PassToJs(JNIEnv *env, jobject obj,
+static void PassToJs(JNIEnv* env, jobject obj, jint nativeClass,
jint generation, jstring currentText, jint keyCode,
jint keyValue, jboolean down, jboolean cap, jboolean fn, jboolean sym)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
WTF::String current = jstringToWtfString(env, currentText);
- GET_NATIVE_VIEW(env, obj)->passToJs(generation, current,
+ reinterpret_cast<WebViewCore*>(nativeClass)->passToJs(generation, current,
PlatformKeyboardEvent(keyCode, keyValue, 0, down, cap, fn, sym));
}
-static void ScrollFocusedTextInput(JNIEnv *env, jobject obj, jfloat xPercent,
- jint y)
+static void ScrollFocusedTextInput(JNIEnv* env, jobject obj, jint nativeClass,
+ jfloat xPercent, jint y, jobject contentBounds)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- viewImpl->scrollFocusedTextInput(xPercent, y);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ IntRect bounds = viewImpl->scrollFocusedTextInput(xPercent, y);
+ if (contentBounds)
+ GraphicsJNI::irect_to_jrect(bounds, env, contentBounds);
}
-static void SetFocusControllerActive(JNIEnv *env, jobject obj, jboolean active)
+static void SetFocusControllerActive(JNIEnv* env, jobject obj, jint nativeClass,
+ jboolean active)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- LOGV("webviewcore::nativeSetFocusControllerActive()\n");
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetFocusControllerActive");
+ ALOGV("webviewcore::nativeSetFocusControllerActive()\n");
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSetFocusControllerActive");
viewImpl->setFocusControllerActive(active);
}
-static void SaveDocumentState(JNIEnv *env, jobject obj, jint frame)
+static void SaveDocumentState(JNIEnv* env, jobject obj, jint nativeClass)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- LOGV("webviewcore::nativeSaveDocumentState()\n");
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in nativeSaveDocumentState");
- viewImpl->saveDocumentState((WebCore::Frame*) frame);
+ ALOGV("webviewcore::nativeSaveDocumentState()\n");
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSaveDocumentState");
+ viewImpl->saveDocumentState(viewImpl->focusedFrame());
}
void WebViewCore::addVisitedLink(const UChar* string, int length)
@@ -4113,53 +4536,26 @@ void WebViewCore::addVisitedLink(const UChar* string, int length)
m_groupForVisitedLinks->addVisitedLink(string, length);
}
-static bool UpdateLayers(JNIEnv *env, jobject obj, jint nativeClass, jint jbaseLayer)
-{
- WebViewCore* viewImpl = (WebViewCore*) nativeClass;
- BaseLayerAndroid* baseLayer = (BaseLayerAndroid*) jbaseLayer;
- if (baseLayer) {
- LayerAndroid* root = static_cast<LayerAndroid*>(baseLayer->getChild(0));
- if (root)
- return viewImpl->updateLayers(root);
- }
- return true;
-}
-
-static void NotifyAnimationStarted(JNIEnv *env, jobject obj, jint nativeClass)
+static void NotifyAnimationStarted(JNIEnv* env, jobject obj, jint nativeClass)
{
WebViewCore* viewImpl = (WebViewCore*) nativeClass;
viewImpl->notifyAnimationStarted();
}
-static jint RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
+static jint RecordContent(JNIEnv* env, jobject obj, jint nativeClass, jobject pt)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- SkRegion* nativeRegion = GraphicsJNI::getNativeRegion(env, region);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
SkIPoint nativePt;
- BaseLayerAndroid* result = viewImpl->recordContent(nativeRegion, &nativePt);
+ BaseLayerAndroid* result = viewImpl->recordContent(&nativePt);
GraphicsJNI::ipoint_to_jpoint(nativePt, env, pt);
return reinterpret_cast<jint>(result);
}
-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(reinterpret_cast<PictureSet*>(content));
-}
-
-static void SendListBoxChoice(JNIEnv* env, jobject obj, jint choice)
+static void SendListBoxChoice(JNIEnv* env, jobject obj, jint nativeClass,
+ jint choice)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoice");
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoice");
viewImpl->popupReply(choice);
}
@@ -4169,14 +4565,11 @@ static void SendListBoxChoice(JNIEnv* env, jobject obj, jint choice)
// number of items in the average multiple-select listbox.
#define PREPARED_LISTBOX_STORAGE 10
-static void SendListBoxChoices(JNIEnv* env, jobject obj, jbooleanArray jArray,
- jint size)
+static void SendListBoxChoices(JNIEnv* env, jobject obj, jint nativeClass,
+ jbooleanArray jArray, jint size)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoices");
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoices");
jboolean* ptrArray = env->GetBooleanArrayElements(jArray, 0);
SkAutoSTMalloc<PREPARED_LISTBOX_STORAGE, int> storage(size);
int* array = storage.get();
@@ -4190,21 +4583,19 @@ static void SendListBoxChoices(JNIEnv* env, jobject obj, jbooleanArray jArray,
viewImpl->popupReply(array, count);
}
-static jstring FindAddress(JNIEnv *env, jobject obj, jstring addr,
- jboolean caseInsensitive)
+// TODO: Move this to WebView.cpp since it is only needed there
+static jstring FindAddress(JNIEnv* env, jobject obj, jstring addr,
+ jboolean caseInsensitive)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
if (!addr)
return 0;
int length = env->GetStringLength(addr);
if (!length)
return 0;
const jchar* addrChars = env->GetStringChars(addr, 0);
- int start, end;
- bool success = CacheBuilder::FindAddress(addrChars, length,
- &start, &end, caseInsensitive) == CacheBuilder::FOUND_COMPLETE;
+ size_t start, end;
+ AddressDetector detector;
+ bool success = detector.FindContent(addrChars, addrChars + length, &start, &end);
jstring ret = 0;
if (success)
ret = env->NewString(addrChars + start, end - start);
@@ -4212,15 +4603,12 @@ static jstring FindAddress(JNIEnv *env, jobject obj, jstring addr,
return ret;
}
-static jboolean HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jintArray idArray,
- jintArray xArray, jintArray yArray,
- jint count, jint actionIndex, jint metaState)
+static jint HandleTouchEvent(JNIEnv* env, jobject obj, jint nativeClass,
+ jint action, jintArray idArray, jintArray xArray, jintArray yArray,
+ jint count, jint actionIndex, jint metaState)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
jint* ptrIdArray = env->GetIntArrayElements(idArray, 0);
jint* ptrXArray = env->GetIntArrayElements(xArray, 0);
jint* ptrYArray = env->GetIntArrayElements(yArray, 0);
@@ -4238,105 +4626,53 @@ static jboolean HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jintArra
return viewImpl->handleTouchEvent(action, ids, points, actionIndex, metaState);
}
-static void TouchUp(JNIEnv *env, jobject obj, jint touchGeneration,
- jint frame, jint node, jint x, jint y)
+static bool MouseClick(JNIEnv* env, jobject obj, jint nativeClass)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
- viewImpl->touchUp(touchGeneration,
- (WebCore::Frame*) frame, (WebCore::Node*) node, x, y);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ return viewImpl->performMouseClick();
}
-static jstring RetrieveHref(JNIEnv *env, jobject obj, jint x, jint y)
+static jstring RetrieveHref(JNIEnv* env, jobject obj, jint nativeClass,
+ jint x, jint y)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
WTF::String result = viewImpl->retrieveHref(x, y);
if (!result.isEmpty())
return wtfStringToJstring(env, result);
return 0;
}
-static jstring RetrieveAnchorText(JNIEnv *env, jobject obj, jint x, jint y)
+static jstring RetrieveAnchorText(JNIEnv* env, jobject obj, jint nativeClass,
+ jint x, jint y)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
WTF::String result = viewImpl->retrieveAnchorText(x, y);
if (!result.isEmpty())
return wtfStringToJstring(env, result);
return 0;
}
-static jstring RetrieveImageSource(JNIEnv *env, jobject obj, jint x, jint y)
-{
- WTF::String result = GET_NATIVE_VIEW(env, obj)->retrieveImageSource(x, y);
- return !result.isEmpty() ? wtfStringToJstring(env, result) : 0;
-}
-
-static void StopPaintingCaret(JNIEnv *env, jobject obj)
-{
- GET_NATIVE_VIEW(env, obj)->setShouldPaintCaret(false);
-}
-
-static void MoveFocus(JNIEnv *env, jobject obj, jint framePtr, jint nodePtr)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
- viewImpl->moveFocus((WebCore::Frame*) framePtr, (WebCore::Node*) nodePtr);
-}
-
-static void MoveMouse(JNIEnv *env, jobject obj, jint frame,
+static jstring RetrieveImageSource(JNIEnv* env, jobject obj, jint nativeClass,
jint x, jint y)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
- viewImpl->moveMouse((WebCore::Frame*) frame, x, y);
-}
-
-static void MoveMouseIfLatest(JNIEnv *env, jobject obj, jint moveGeneration,
- jint frame, jint x, jint y)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
- viewImpl->moveMouseIfLatest(moveGeneration,
- (WebCore::Frame*) frame, x, y);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ WTF::String result = viewImpl->retrieveImageSource(x, y);
+ return !result.isEmpty() ? wtfStringToJstring(env, result) : 0;
}
-static void UpdateFrameCache(JNIEnv *env, jobject obj)
+static void MoveMouse(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
- viewImpl->updateFrameCache();
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ viewImpl->moveMouse(x, y);
}
-static jint GetContentMinPrefWidth(JNIEnv *env, jobject obj)
+static jint GetContentMinPrefWidth(JNIEnv* env, jobject obj, jint nativeClass)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
WebCore::Frame* frame = viewImpl->mainFrame();
if (frame) {
@@ -4351,13 +4687,11 @@ static jint GetContentMinPrefWidth(JNIEnv *env, jobject obj)
return 0;
}
-static void SetViewportSettingsFromNative(JNIEnv *env, jobject obj)
+static void SetViewportSettingsFromNative(JNIEnv* env, jobject obj,
+ jint nativeClass)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
WebCore::Settings* s = viewImpl->mainFrame()->page()->settings();
if (!s)
@@ -4374,66 +4708,49 @@ static void SetViewportSettingsFromNative(JNIEnv *env, jobject obj)
#endif
}
-static void SetBackgroundColor(JNIEnv *env, jobject obj, jint color)
+static void SetBackgroundColor(JNIEnv* env, jobject obj, jint nativeClass,
+ jint color)
{
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
viewImpl->setBackgroundColor((SkColor) color);
}
-static void DumpDomTree(JNIEnv *env, jobject obj, jboolean useFile)
+static void DumpDomTree(JNIEnv* env, jobject obj, jint nativeClass,
+ jboolean useFile)
{
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
viewImpl->dumpDomTree(useFile);
}
-static void DumpRenderTree(JNIEnv *env, jobject obj, jboolean useFile)
+static void DumpRenderTree(JNIEnv* env, jobject obj, jint nativeClass,
+ jboolean useFile)
{
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
viewImpl->dumpRenderTree(useFile);
}
-static void DumpNavTree(JNIEnv *env, jobject obj)
-{
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
-
- viewImpl->dumpNavTree();
-}
-
-static void DumpV8Counters(JNIEnv*, jobject)
+static void SetJsFlags(JNIEnv* env, jobject obj, jint nativeClass, jstring flags)
{
-#if USE(V8)
-#ifdef ANDROID_INSTRUMENT
- V8Counters::dumpCounters();
-#endif
-#endif
-}
-
-static void SetJsFlags(JNIEnv *env, jobject obj, jstring flags)
-{
-#if USE(V8)
WTF::String flagsString = jstringToWtfString(env, flags);
WTF::CString utf8String = flagsString.utf8();
WebCore::ScriptController::setFlags(utf8String.data(), utf8String.length());
-#endif
}
// Called from the Java side to set a new quota for the origin or new appcache
// max size in response to a notification that the original quota was exceeded or
// that the appcache has reached its maximum size.
-static void SetNewStorageLimit(JNIEnv* env, jobject obj, jlong quota) {
+static void SetNewStorageLimit(JNIEnv* env, jobject obj, jint nativeClass,
+ jlong quota)
+{
#if ENABLE(DATABASE) || ENABLE(OFFLINE_WEB_APPLICATIONS)
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
Frame* frame = viewImpl->mainFrame();
// The main thread is blocked awaiting this response, so now we can wake it
@@ -4444,93 +4761,102 @@ static void SetNewStorageLimit(JNIEnv* env, jobject obj, jlong quota) {
}
// Called from Java to provide a Geolocation permission state for the specified origin.
-static void GeolocationPermissionsProvide(JNIEnv* env, jobject obj, jstring origin, jboolean allow, jboolean remember) {
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+static void GeolocationPermissionsProvide(JNIEnv* env, jobject obj,
+ jint nativeClass, jstring origin, jboolean allow, jboolean remember)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
Frame* frame = viewImpl->mainFrame();
ChromeClientAndroid* chromeClient = static_cast<ChromeClientAndroid*>(frame->page()->chrome()->client());
chromeClient->provideGeolocationPermissions(jstringToWtfString(env, origin), allow, remember);
}
-static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jstring scheme) {
-#ifdef ANDROID_INSTRUMENT
- TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
-#endif
+static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jint nativeClass,
+ jstring scheme)
+{
WebCore::SchemeRegistry::registerURLSchemeAsLocal(jstringToWtfString(env, scheme));
}
-static bool FocusBoundsChanged(JNIEnv* env, jobject obj)
+static bool FocusBoundsChanged(JNIEnv* env, jobject obj, jint nativeClass)
{
- return GET_NATIVE_VIEW(env, obj)->focusBoundsChanged();
+ return reinterpret_cast<WebViewCore*>(nativeClass)->focusBoundsChanged();
}
-static void SetIsPaused(JNIEnv* env, jobject obj, jboolean isPaused)
+static void SetIsPaused(JNIEnv* env, jobject obj, jint nativeClass,
+ jboolean isPaused)
{
// tell the webcore thread to stop thinking while we do other work
// (selection and scrolling). This has nothing to do with the lifecycle
// pause and resume.
- GET_NATIVE_VIEW(env, obj)->setIsPaused(isPaused);
+ reinterpret_cast<WebViewCore*>(nativeClass)->setIsPaused(isPaused);
}
-static void Pause(JNIEnv* env, jobject obj)
+static void Pause(JNIEnv* env, jobject obj, jint nativeClass)
{
// This is called for the foreground tab when the browser is put to the
// background (and also for any tab when it is put to the background of the
// browser). The browser can only be killed by the system when it is in the
// background, so saving the Geolocation permission state now ensures that
// is maintained when the browser is killed.
- ChromeClient* chromeClient = GET_NATIVE_VIEW(env, obj)->mainFrame()->page()->chrome()->client();
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ChromeClient* chromeClient = viewImpl->mainFrame()->page()->chrome()->client();
ChromeClientAndroid* chromeClientAndroid = static_cast<ChromeClientAndroid*>(chromeClient);
chromeClientAndroid->storeGeolocationPermissions();
- Frame* mainFrame = GET_NATIVE_VIEW(env, obj)->mainFrame();
+ Frame* mainFrame = viewImpl->mainFrame();
for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
if (geolocation)
geolocation->suspend();
}
+ if (mainFrame)
+ mainFrame->settings()->setMinDOMTimerInterval(BACKGROUND_TIMER_INTERVAL);
- GET_NATIVE_VIEW(env, obj)->deviceMotionAndOrientationManager()->maybeSuspendClients();
+ viewImpl->deviceMotionAndOrientationManager()->maybeSuspendClients();
ANPEvent event;
SkANP::InitEvent(&event, kLifecycle_ANPEventType);
event.data.lifecycle.action = kPause_ANPLifecycleAction;
- GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
+ viewImpl->sendPluginEvent(event);
- GET_NATIVE_VIEW(env, obj)->setIsPaused(true);
+ viewImpl->setIsPaused(true);
}
-static void Resume(JNIEnv* env, jobject obj)
+static void Resume(JNIEnv* env, jobject obj, jint nativeClass)
{
- Frame* mainFrame = GET_NATIVE_VIEW(env, obj)->mainFrame();
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ Frame* mainFrame = viewImpl->mainFrame();
for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
if (geolocation)
geolocation->resume();
}
+ if (mainFrame)
+ mainFrame->settings()->setMinDOMTimerInterval(FOREGROUND_TIMER_INTERVAL);
- GET_NATIVE_VIEW(env, obj)->deviceMotionAndOrientationManager()->maybeResumeClients();
+ viewImpl->deviceMotionAndOrientationManager()->maybeResumeClients();
ANPEvent event;
SkANP::InitEvent(&event, kLifecycle_ANPEventType);
event.data.lifecycle.action = kResume_ANPLifecycleAction;
- GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
+ viewImpl->sendPluginEvent(event);
- GET_NATIVE_VIEW(env, obj)->setIsPaused(false);
+ viewImpl->setIsPaused(false);
}
-static void FreeMemory(JNIEnv* env, jobject obj)
+static void FreeMemory(JNIEnv* env, jobject obj, jint nativeClass)
{
ANPEvent event;
SkANP::InitEvent(&event, kLifecycle_ANPEventType);
event.data.lifecycle.action = kFreeMemory_ANPLifecycleAction;
- GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
+ reinterpret_cast<WebViewCore*>(nativeClass)->sendPluginEvent(event);
}
-static void ProvideVisitedHistory(JNIEnv *env, jobject obj, jobject hist)
+static void ProvideVisitedHistory(JNIEnv* env, jobject obj, jint nativeClass,
+ jobject hist)
{
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
jobjectArray array = static_cast<jobjectArray>(hist);
@@ -4545,78 +4871,38 @@ static void ProvideVisitedHistory(JNIEnv *env, jobject obj, jobject hist)
}
}
-static void PluginSurfaceReady(JNIEnv* env, jobject obj)
+static void PluginSurfaceReady(JNIEnv* env, jobject obj, jint nativeClass)
{
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
if (viewImpl)
viewImpl->sendPluginSurfaceReady();
}
// Notification from the UI thread that the plugin's full-screen surface has been discarded
-static void FullScreenPluginHidden(JNIEnv* env, jobject obj, jint npp)
+static void FullScreenPluginHidden(JNIEnv* env, jobject obj, jint nativeClass,
+ jint npp)
{
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
PluginWidgetAndroid* plugin = viewImpl->getPluginWidget((NPP)npp);
if (plugin)
plugin->exitFullScreen(false);
}
-static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
-{
- int L, T, R, B;
- GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B);
- return WebCore::IntRect(L, T, R - L, B - T);
-}
-
-static bool ValidNodeAndBounds(JNIEnv *env, jobject obj, int frame, int node,
- jobject rect)
-{
- IntRect nativeRect = jrect_to_webrect(env, rect);
- return GET_NATIVE_VIEW(env, obj)->validNodeAndBounds(
- reinterpret_cast<Frame*>(frame),
- reinterpret_cast<Node*>(node), nativeRect);
-}
-
-static jobject GetTouchHighlightRects(JNIEnv* env, jobject obj, jint x, jint y, jint slop)
+static jobject HitTest(JNIEnv* env, jobject obj, jint nativeClass, jint x,
+ jint y, jint slop, jboolean doMoveMouse)
{
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
if (!viewImpl)
return 0;
- Vector<IntRect> rects = viewImpl->getTouchHighlightRects(x, y, slop);
- if (rects.isEmpty())
- return 0;
-
- 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(array, "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].maxX(), rects[i].maxY());
- if (rect) {
- env->CallBooleanMethod(array, add, rect);
- env->DeleteLocalRef(rect);
- }
- }
-
- env->DeleteLocalRef(rectClass);
- env->DeleteLocalRef(arrayClass);
- return array;
+ AndroidHitTestResult result = viewImpl->hitTestAtPoint(x, y, slop, doMoveMouse);
+ return result.createJavaObject(env);
}
-static void AutoFillForm(JNIEnv* env, jobject obj, jint queryId)
+static void AutoFillForm(JNIEnv* env, jobject obj, jint nativeClass,
+ jint queryId)
{
#if ENABLE(WEB_AUTOFILL)
- WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
if (!viewImpl)
return;
@@ -4629,19 +4915,87 @@ static void AutoFillForm(JNIEnv* env, jobject obj, jint queryId)
#endif
}
-static void CloseIdleConnections(JNIEnv* env, jobject obj)
+static void CloseIdleConnections(JNIEnv* env, jobject obj, jint nativeClass)
{
-#if USE(CHROME_NETWORK_STACK)
WebCache::get(true)->closeIdleConnections();
WebCache::get(false)->closeIdleConnections();
-#endif
}
-static void ScrollRenderLayer(JNIEnv* env, jobject obj, jint layer, jobject jRect)
+static void nativeCertTrustChanged(JNIEnv *env, jobject obj)
+{
+ WebCache::get(true)->certTrustChanged();
+ WebCache::get(false)->certTrustChanged();
+}
+
+static void ScrollRenderLayer(JNIEnv* env, jobject obj, jint nativeClass,
+ jint layer, jobject jRect)
{
SkRect rect;
GraphicsJNI::jrect_to_rect(env, jRect, &rect);
- GET_NATIVE_VIEW(env, obj)->scrollRenderLayer(layer, rect);
+ reinterpret_cast<WebViewCore*>(nativeClass)->scrollRenderLayer(layer, rect);
+}
+
+static void DeleteText(JNIEnv* env, jobject obj, jint nativeClass,
+ jint startX, jint startY, jint endX, jint endY)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ viewImpl->deleteText(startX, startY, endX, endY);
+}
+
+static void InsertText(JNIEnv* env, jobject obj, jint nativeClass,
+ jstring text)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ WTF::String wtfText = jstringToWtfString(env, text);
+ viewImpl->insertText(wtfText);
+}
+
+static jobject GetText(JNIEnv* env, jobject obj, jint nativeClass,
+ jint startX, jint startY, jint endX, jint endY)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ WTF::String text = viewImpl->getText(startX, startY, endX, endY);
+ return text.isEmpty() ? 0 : wtfStringToJstring(env, text);
+}
+
+static void SelectText(JNIEnv* env, jobject obj, jint nativeClass,
+ jint startX, jint startY, jint endX, jint endY)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ viewImpl->selectText(startX, startY, endX, endY);
+}
+
+static void ClearSelection(JNIEnv* env, jobject obj, jint nativeClass)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ viewImpl->focusedFrame()->selection()->clear();
+}
+
+static bool SelectWordAt(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ return viewImpl->selectWordAt(x, y);
+}
+
+static void SelectAll(JNIEnv* env, jobject obj, jint nativeClass)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ viewImpl->focusedFrame()->selection()->selectAll();
+}
+
+static int FindAll(JNIEnv* env, jobject obj, jint nativeClass,
+ jstring text)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ WTF::String wtfText = jstringToWtfString(env, text);
+ return viewImpl->findTextOnPage(wtfText);
+}
+
+static int FindNext(JNIEnv* env, jobject obj, jint nativeClass,
+ jboolean forward)
+{
+ WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+ return viewImpl->findNextOnPage(forward);
}
// ----------------------------------------------------------------------------
@@ -4650,164 +5004,159 @@ static void ScrollRenderLayer(JNIEnv* env, jobject obj, jint layer, jobject jRec
* JNI registration.
*/
static JNINativeMethod gJavaWebViewCoreMethods[] = {
- { "nativeClearContent", "()V",
+ { "nativeClearContent", "(I)V",
(void*) ClearContent },
- { "nativeFocusBoundsChanged", "()Z",
+ { "nativeFocusBoundsChanged", "(I)Z",
(void*) FocusBoundsChanged } ,
- { "nativeKey", "(IIIZZZZ)Z",
+ { "nativeKey", "(IIIIZZZZ)Z",
(void*) Key },
- { "nativeClick", "(IIZ)V",
- (void*) Click },
- { "nativeContentInvalidateAll", "()V",
+ { "nativeContentInvalidateAll", "(I)V",
(void*) ContentInvalidateAll },
- { "nativeSendListBoxChoices", "([ZI)V",
+ { "nativeSendListBoxChoices", "(I[ZI)V",
(void*) SendListBoxChoices },
- { "nativeSendListBoxChoice", "(I)V",
+ { "nativeSendListBoxChoice", "(II)V",
(void*) SendListBoxChoice },
- { "nativeSetSize", "(IIIFIIIIZ)V",
+ { "nativeSetSize", "(IIIIFIIIIZ)V",
(void*) SetSize },
{ "nativeSetScrollOffset", "(IZII)V",
(void*) SetScrollOffset },
- { "nativeSetGlobalBounds", "(IIII)V",
+ { "nativeSetGlobalBounds", "(IIIII)V",
(void*) SetGlobalBounds },
- { "nativeSetSelection", "(II)V",
+ { "nativeSetSelection", "(III)V",
(void*) SetSelection } ,
- { "nativeModifySelection", "(II)Ljava/lang/String;",
+ { "nativeModifySelection", "(III)Ljava/lang/String;",
(void*) ModifySelection },
- { "nativeDeleteSelection", "(III)V",
+ { "nativeDeleteSelection", "(IIII)V",
(void*) DeleteSelection } ,
- { "nativeReplaceTextfieldText", "(IILjava/lang/String;III)V",
+ { "nativeReplaceTextfieldText", "(IIILjava/lang/String;III)V",
(void*) ReplaceTextfieldText } ,
- { "nativeMoveFocus", "(II)V",
- (void*) MoveFocus },
{ "nativeMoveMouse", "(III)V",
(void*) MoveMouse },
- { "nativeMoveMouseIfLatest", "(IIII)V",
- (void*) MoveMouseIfLatest },
- { "passToJs", "(ILjava/lang/String;IIZZZZ)V",
+ { "passToJs", "(IILjava/lang/String;IIZZZZ)V",
(void*) PassToJs },
- { "nativeScrollFocusedTextInput", "(FI)V",
+ { "nativeScrollFocusedTextInput", "(IFILandroid/graphics/Rect;)V",
(void*) ScrollFocusedTextInput },
- { "nativeSetFocusControllerActive", "(Z)V",
+ { "nativeSetFocusControllerActive", "(IZ)V",
(void*) SetFocusControllerActive },
{ "nativeSaveDocumentState", "(I)V",
(void*) SaveDocumentState },
{ "nativeFindAddress", "(Ljava/lang/String;Z)Ljava/lang/String;",
(void*) FindAddress },
- { "nativeHandleTouchEvent", "(I[I[I[IIII)Z",
- (void*) HandleTouchEvent },
- { "nativeTouchUp", "(IIIII)V",
- (void*) TouchUp },
- { "nativeRetrieveHref", "(II)Ljava/lang/String;",
+ { "nativeHandleTouchEvent", "(II[I[I[IIII)I",
+ (void*) HandleTouchEvent },
+ { "nativeMouseClick", "(I)Z",
+ (void*) MouseClick },
+ { "nativeRetrieveHref", "(III)Ljava/lang/String;",
(void*) RetrieveHref },
- { "nativeRetrieveAnchorText", "(II)Ljava/lang/String;",
+ { "nativeRetrieveAnchorText", "(III)Ljava/lang/String;",
(void*) RetrieveAnchorText },
- { "nativeRetrieveImageSource", "(II)Ljava/lang/String;",
+ { "nativeRetrieveImageSource", "(III)Ljava/lang/String;",
(void*) RetrieveImageSource },
- { "nativeStopPaintingCaret", "()V",
- (void*) StopPaintingCaret },
- { "nativeUpdateFrameCache", "()V",
- (void*) UpdateFrameCache },
- { "nativeGetContentMinPrefWidth", "()I",
+ { "nativeGetContentMinPrefWidth", "(I)I",
(void*) GetContentMinPrefWidth },
- { "nativeUpdateLayers", "(II)Z",
- (void*) UpdateLayers },
{ "nativeNotifyAnimationStarted", "(I)V",
(void*) NotifyAnimationStarted },
- { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)I",
+ { "nativeRecordContent", "(ILandroid/graphics/Point;)I",
(void*) RecordContent },
- { "setViewportSettingsFromNative", "()V",
+ { "setViewportSettingsFromNative", "(I)V",
(void*) SetViewportSettingsFromNative },
- { "nativeSplitContent", "(I)V",
- (void*) SplitContent },
- { "nativeSetBackgroundColor", "(I)V",
+ { "nativeSetBackgroundColor", "(II)V",
(void*) SetBackgroundColor },
- { "nativeRegisterURLSchemeAsLocal", "(Ljava/lang/String;)V",
+ { "nativeRegisterURLSchemeAsLocal", "(ILjava/lang/String;)V",
(void*) RegisterURLSchemeAsLocal },
- { "nativeDumpDomTree", "(Z)V",
+ { "nativeDumpDomTree", "(IZ)V",
(void*) DumpDomTree },
- { "nativeDumpRenderTree", "(Z)V",
+ { "nativeDumpRenderTree", "(IZ)V",
(void*) DumpRenderTree },
- { "nativeDumpNavTree", "()V",
- (void*) DumpNavTree },
- { "nativeDumpV8Counters", "()V",
- (void*) DumpV8Counters },
- { "nativeSetNewStorageLimit", "(J)V",
+ { "nativeSetNewStorageLimit", "(IJ)V",
(void*) SetNewStorageLimit },
- { "nativeGeolocationPermissionsProvide", "(Ljava/lang/String;ZZ)V",
+ { "nativeGeolocationPermissionsProvide", "(ILjava/lang/String;ZZ)V",
(void*) GeolocationPermissionsProvide },
- { "nativeSetIsPaused", "(Z)V", (void*) SetIsPaused },
- { "nativePause", "()V", (void*) Pause },
- { "nativeResume", "()V", (void*) Resume },
- { "nativeFreeMemory", "()V", (void*) FreeMemory },
- { "nativeSetJsFlags", "(Ljava/lang/String;)V", (void*) SetJsFlags },
- { "nativeRequestLabel", "(II)Ljava/lang/String;",
+ { "nativeSetIsPaused", "(IZ)V", (void*) SetIsPaused },
+ { "nativePause", "(I)V", (void*) Pause },
+ { "nativeResume", "(I)V", (void*) Resume },
+ { "nativeFreeMemory", "(I)V", (void*) FreeMemory },
+ { "nativeSetJsFlags", "(ILjava/lang/String;)V", (void*) SetJsFlags },
+ { "nativeRequestLabel", "(III)Ljava/lang/String;",
(void*) RequestLabel },
- { "nativeRevealSelection", "()V", (void*) RevealSelection },
- { "nativeUpdateFrameCacheIfLoading", "()V",
- (void*) UpdateFrameCacheIfLoading },
- { "nativeProvideVisitedHistory", "([Ljava/lang/String;)V",
+ { "nativeRevealSelection", "(I)V", (void*) RevealSelection },
+ { "nativeProvideVisitedHistory", "(I[Ljava/lang/String;)V",
(void*) ProvideVisitedHistory },
- { "nativeFullScreenPluginHidden", "(I)V",
+ { "nativeFullScreenPluginHidden", "(II)V",
(void*) FullScreenPluginHidden },
- { "nativePluginSurfaceReady", "()V",
+ { "nativePluginSurfaceReady", "(I)V",
(void*) PluginSurfaceReady },
- { "nativeValidNodeAndBounds", "(IILandroid/graphics/Rect;)Z",
- (void*) ValidNodeAndBounds },
- { "nativeGetTouchHighlightRects", "(III)Ljava/util/ArrayList;",
- (void*) GetTouchHighlightRects },
- { "nativeAutoFillForm", "(I)V",
+ { "nativeHitTest", "(IIIIZ)Landroid/webkit/WebViewCore$WebKitHitTest;",
+ (void*) HitTest },
+ { "nativeAutoFillForm", "(II)V",
(void*) AutoFillForm },
- { "nativeScrollLayer", "(ILandroid/graphics/Rect;)V",
+ { "nativeScrollLayer", "(IILandroid/graphics/Rect;)V",
(void*) ScrollRenderLayer },
- { "nativeCloseIdleConnections", "()V",
+ { "nativeCloseIdleConnections", "(I)V",
(void*) CloseIdleConnections },
+ { "nativeDeleteText", "(IIIII)V",
+ (void*) DeleteText },
+ { "nativeInsertText", "(ILjava/lang/String;)V",
+ (void*) InsertText },
+ { "nativeGetText", "(IIIII)Ljava/lang/String;",
+ (void*) GetText },
+ { "nativeSelectText", "(IIIII)V",
+ (void*) SelectText },
+ { "nativeClearTextSelection", "(I)V",
+ (void*) ClearSelection },
+ { "nativeSelectWordAt", "(III)Z",
+ (void*) SelectWordAt },
+ { "nativeSelectAll", "(I)V",
+ (void*) SelectAll },
+ { "nativeCertTrustChanged","()V",
+ (void*) nativeCertTrustChanged },
+ { "nativeFindAll", "(ILjava/lang/String;)I",
+ (void*) FindAll },
+ { "nativeFindNext", "(IZ)I",
+ (void*) FindNext },
+ { "nativeSetInitialFocus", "(II)V", (void*) SetInitialFocus },
};
int registerWebViewCore(JNIEnv* env)
{
jclass widget = env->FindClass("android/webkit/WebViewCore");
- LOG_ASSERT(widget,
+ ALOG_ASSERT(widget,
"Unable to find class android/webkit/WebViewCore");
gWebViewCoreFields.m_nativeClass = env->GetFieldID(widget, "mNativeClass",
"I");
- LOG_ASSERT(gWebViewCoreFields.m_nativeClass,
+ ALOG_ASSERT(gWebViewCoreFields.m_nativeClass,
"Unable to find android/webkit/WebViewCore.mNativeClass");
gWebViewCoreFields.m_viewportWidth = env->GetFieldID(widget,
"mViewportWidth", "I");
- LOG_ASSERT(gWebViewCoreFields.m_viewportWidth,
+ ALOG_ASSERT(gWebViewCoreFields.m_viewportWidth,
"Unable to find android/webkit/WebViewCore.mViewportWidth");
gWebViewCoreFields.m_viewportHeight = env->GetFieldID(widget,
"mViewportHeight", "I");
- LOG_ASSERT(gWebViewCoreFields.m_viewportHeight,
+ ALOG_ASSERT(gWebViewCoreFields.m_viewportHeight,
"Unable to find android/webkit/WebViewCore.mViewportHeight");
gWebViewCoreFields.m_viewportInitialScale = env->GetFieldID(widget,
"mViewportInitialScale", "I");
- LOG_ASSERT(gWebViewCoreFields.m_viewportInitialScale,
+ ALOG_ASSERT(gWebViewCoreFields.m_viewportInitialScale,
"Unable to find android/webkit/WebViewCore.mViewportInitialScale");
gWebViewCoreFields.m_viewportMinimumScale = env->GetFieldID(widget,
"mViewportMinimumScale", "I");
- LOG_ASSERT(gWebViewCoreFields.m_viewportMinimumScale,
+ ALOG_ASSERT(gWebViewCoreFields.m_viewportMinimumScale,
"Unable to find android/webkit/WebViewCore.mViewportMinimumScale");
gWebViewCoreFields.m_viewportMaximumScale = env->GetFieldID(widget,
"mViewportMaximumScale", "I");
- LOG_ASSERT(gWebViewCoreFields.m_viewportMaximumScale,
+ ALOG_ASSERT(gWebViewCoreFields.m_viewportMaximumScale,
"Unable to find android/webkit/WebViewCore.mViewportMaximumScale");
gWebViewCoreFields.m_viewportUserScalable = env->GetFieldID(widget,
"mViewportUserScalable", "Z");
- LOG_ASSERT(gWebViewCoreFields.m_viewportUserScalable,
+ ALOG_ASSERT(gWebViewCoreFields.m_viewportUserScalable,
"Unable to find android/webkit/WebViewCore.mViewportUserScalable");
gWebViewCoreFields.m_viewportDensityDpi = env->GetFieldID(widget,
"mViewportDensityDpi", "I");
- LOG_ASSERT(gWebViewCoreFields.m_viewportDensityDpi,
+ ALOG_ASSERT(gWebViewCoreFields.m_viewportDensityDpi,
"Unable to find android/webkit/WebViewCore.mViewportDensityDpi");
- gWebViewCoreFields.m_webView = env->GetFieldID(widget,
- "mWebView", "Landroid/webkit/WebView;");
- LOG_ASSERT(gWebViewCoreFields.m_webView,
- "Unable to find android/webkit/WebViewCore.mWebView");
gWebViewCoreFields.m_drawIsPaused = env->GetFieldID(widget,
"mDrawIsPaused", "Z");
- LOG_ASSERT(gWebViewCoreFields.m_drawIsPaused,
+ ALOG_ASSERT(gWebViewCoreFields.m_drawIsPaused,
"Unable to find android/webkit/WebViewCore.mDrawIsPaused");
gWebViewCoreFields.m_lowMemoryUsageMb = env->GetFieldID(widget, "mLowMemoryUsageThresholdMb", "I");
gWebViewCoreFields.m_highMemoryUsageMb = env->GetFieldID(widget, "mHighMemoryUsageThresholdMb", "I");