diff options
Diffstat (limited to 'Source/WebKit/android')
| -rw-r--r-- | Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp | 11 | ||||
| -rw-r--r-- | Source/WebKit/android/jni/AndroidHitTestResult.cpp | 4 | ||||
| -rw-r--r-- | Source/WebKit/android/jni/ViewStateSerializer.cpp | 135 | ||||
| -rw-r--r-- | Source/WebKit/android/jni/WebViewCore.cpp | 51 | ||||
| -rw-r--r-- | Source/WebKit/android/jni/WebViewCore.h | 4 | ||||
| -rw-r--r-- | Source/WebKit/android/nav/WebView.cpp | 2 |
6 files changed, 161 insertions, 46 deletions
diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index 1328675..5e16152 100644 --- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -161,8 +161,15 @@ void ChromeClientAndroid::focus() } void ChromeClientAndroid::unfocus() { notImplemented(); } -bool ChromeClientAndroid::canTakeFocus(FocusDirection) { notImplemented(); return false; } -void ChromeClientAndroid::takeFocus(FocusDirection) { notImplemented(); } +bool ChromeClientAndroid::canTakeFocus(FocusDirection direction) +{ + return android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->chromeCanTakeFocus(direction); +} + +void ChromeClientAndroid::takeFocus(FocusDirection direction) +{ + android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->chromeTakeFocus(direction); +} void ChromeClientAndroid::focusedNodeChanged(Node* node) { diff --git a/Source/WebKit/android/jni/AndroidHitTestResult.cpp b/Source/WebKit/android/jni/AndroidHitTestResult.cpp index 16dd809..9be5613 100644 --- a/Source/WebKit/android/jni/AndroidHitTestResult.cpp +++ b/Source/WebKit/android/jni/AndroidHitTestResult.cpp @@ -135,11 +135,15 @@ void AndroidHitTestResult::buildHighlightRects() node = m_hitTestResult.innerNode(); if (!node || !node->renderer()) return; + if (!WebViewCore::nodeIsClickableOrFocusable(node)) + return; Frame* frame = node->document()->frame(); IntPoint frameOffset = m_webViewCore->convertGlobalContentToFrameContent(IntPoint(), frame); RenderObject* renderer = node->renderer(); Vector<FloatQuad> quads; renderer->absoluteFocusRingQuads(quads); + if (!quads.size()) + renderer->absoluteQuads(quads); // No fancy rings, grab some backups for (size_t i = 0; i < quads.size(); i++) { IntRect boundingBox = quads[i].enclosingBoundingBox(); boundingBox.move(-frameOffset.x(), -frameOffset.y()); diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp index 6b473f5..a96b6b4 100644 --- a/Source/WebKit/android/jni/ViewStateSerializer.cpp +++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp @@ -27,7 +27,10 @@ #include "BaseLayerAndroid.h" #include "CreateJavaOutputStreamAdaptor.h" +#include "FixedPositioning.h" #include "ImagesManager.h" +#include "IFrameContentLayerAndroid.h" +#include "IFrameLayerAndroid.h" #include "Layer.h" #include "LayerAndroid.h" #include "PictureSet.h" @@ -49,6 +52,9 @@ #undef XLOG #define XLOG(...) +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ViewStateSerializer", __VA_ARGS__) + #endif // DEBUG namespace android { @@ -57,6 +63,7 @@ enum LayerTypes { LTNone = 0, LTLayerAndroid = 1, LTScrollableLayerAndroid = 2, + LTFixedLayerAndroid = 3 }; static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer, @@ -91,8 +98,8 @@ static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer, return true; } -static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jobject jstream, - jbyteArray jstorage) +static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jint version, + jobject jstream, jbyteArray jstorage) { SkStream* stream = CreateJavaInputStreamAdaptor(env, jstream, jstorage); if (!stream) @@ -107,7 +114,7 @@ static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jobjec SkSafeUnref(picture); int childCount = stream->readS32(); for (int i = 0; i < childCount; i++) { - LayerAndroid* childLayer = deserializeLayer(stream); + LayerAndroid* childLayer = deserializeLayer(version, stream); if (childLayer) layer->addChild(childLayer); } @@ -253,9 +260,9 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream) stream->write8(LTNone); return; } - LayerTypes type = layer->contentIsScrollable() - ? LTScrollableLayerAndroid - : LTLayerAndroid; + LayerTypes type = LTLayerAndroid; + if (layer->contentIsScrollable()) + type = LTScrollableLayerAndroid; stream->write8(type); // Start with Layer fields @@ -272,20 +279,43 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream) // Next up, LayerAndroid fields stream->writeBool(layer->m_haveClip); - stream->writeBool(layer->m_isFixed); + stream->writeBool(layer->isFixed()); stream->writeBool(layer->m_backgroundColorSet); - stream->writeBool(layer->m_isIframe); - writeSkLength(stream, layer->m_fixedLeft); - writeSkLength(stream, layer->m_fixedTop); - writeSkLength(stream, layer->m_fixedRight); - writeSkLength(stream, layer->m_fixedBottom); - writeSkLength(stream, layer->m_fixedMarginLeft); - writeSkLength(stream, layer->m_fixedMarginTop); - writeSkLength(stream, layer->m_fixedMarginRight); - writeSkLength(stream, layer->m_fixedMarginBottom); - writeSkRect(stream, layer->m_fixedRect); - stream->write32(layer->m_renderLayerPos.x()); - stream->write32(layer->m_renderLayerPos.y()); + stream->writeBool(layer->isIFrame()); + + // With the current LayerAndroid hierarchy, LayerAndroid doesn't have + // those fields anymore. Let's keep the current serialization format for + // now and output blank fields... not great, but probably better than + // dealing with multiple versions. + if (layer->fixedPosition()) { + FixedPositioning* fixedPosition = layer->fixedPosition(); + writeSkLength(stream, fixedPosition->m_fixedLeft); + writeSkLength(stream, fixedPosition->m_fixedTop); + writeSkLength(stream, fixedPosition->m_fixedRight); + writeSkLength(stream, fixedPosition->m_fixedBottom); + writeSkLength(stream, fixedPosition->m_fixedMarginLeft); + writeSkLength(stream, fixedPosition->m_fixedMarginTop); + writeSkLength(stream, fixedPosition->m_fixedMarginRight); + writeSkLength(stream, fixedPosition->m_fixedMarginBottom); + writeSkRect(stream, fixedPosition->m_fixedRect); + stream->write32(fixedPosition->m_renderLayerPos.x()); + stream->write32(fixedPosition->m_renderLayerPos.y()); + } else { + SkLength length; + SkRect rect; + writeSkLength(stream, length); // fixedLeft + writeSkLength(stream, length); // fixedTop + writeSkLength(stream, length); // fixedRight + writeSkLength(stream, length); // fixedBottom + writeSkLength(stream, length); // fixedMarginLeft + writeSkLength(stream, length); // fixedMarginTop + writeSkLength(stream, length); // fixedMarginRight + writeSkLength(stream, length); // fixedMarginBottom + writeSkRect(stream, rect); // fixedRect + stream->write32(0); // renderLayerPos.x() + stream->write32(0); // renderLayerPos.y() + } + stream->writeBool(layer->m_backfaceVisibility); stream->writeBool(layer->m_visible); stream->write32(layer->m_backgroundColor); @@ -327,7 +357,7 @@ void serializeLayer(LayerAndroid* layer, SkWStream* stream) serializeLayer(layer->getChild(i), stream); } -LayerAndroid* deserializeLayer(SkStream* stream) +LayerAndroid* deserializeLayer(int version, SkStream* stream) { int type = stream->readU8(); if (type == LTNone) @@ -354,20 +384,55 @@ LayerAndroid* deserializeLayer(SkStream* stream) // LayerAndroid fields layer->m_haveClip = stream->readBool(); - layer->m_isFixed = stream->readBool(); + + // Keep the legacy serialization/deserialization format... + bool isFixed = stream->readBool(); + layer->m_backgroundColorSet = stream->readBool(); - layer->m_isIframe = stream->readBool(); - layer->m_fixedLeft = readSkLength(stream); - layer->m_fixedTop = readSkLength(stream); - layer->m_fixedRight = readSkLength(stream); - layer->m_fixedBottom = readSkLength(stream); - layer->m_fixedMarginLeft = readSkLength(stream); - layer->m_fixedMarginTop = readSkLength(stream); - layer->m_fixedMarginRight = readSkLength(stream); - layer->m_fixedMarginBottom = readSkLength(stream); - layer->m_fixedRect = readSkRect(stream); - layer->m_renderLayerPos.setX(stream->readS32()); - layer->m_renderLayerPos.setY(stream->readS32()); + + bool isIframe = stream->readBool(); + // If we are a scrollable layer android, we are an iframe content + if (isIframe && type == LTScrollableLayerAndroid) { + IFrameContentLayerAndroid* iframeContent = new IFrameContentLayerAndroid(*layer); + layer->unref(); + layer = iframeContent; + } else if (isIframe) { // otherwise we are just the iframe (we use it to compute offset) + IFrameLayerAndroid* iframe = new IFrameLayerAndroid(*layer); + layer->unref(); + layer = iframe; + } + + if (isFixed) { + FixedPositioning* fixedPosition = new FixedPositioning(layer); + + fixedPosition->m_fixedLeft = readSkLength(stream); + fixedPosition->m_fixedTop = readSkLength(stream); + fixedPosition->m_fixedRight = readSkLength(stream); + fixedPosition->m_fixedBottom = readSkLength(stream); + fixedPosition->m_fixedMarginLeft = readSkLength(stream); + fixedPosition->m_fixedMarginTop = readSkLength(stream); + fixedPosition->m_fixedMarginRight = readSkLength(stream); + fixedPosition->m_fixedMarginBottom = readSkLength(stream); + fixedPosition->m_fixedRect = readSkRect(stream); + fixedPosition->m_renderLayerPos.setX(stream->readS32()); + fixedPosition->m_renderLayerPos.setY(stream->readS32()); + + layer->setFixedPosition(fixedPosition); + } else { + // Not a fixed element, bypass the values in the stream + readSkLength(stream); // fixedLeft + readSkLength(stream); // fixedTop + readSkLength(stream); // fixedRight + readSkLength(stream); // fixedBottom + readSkLength(stream); // fixedMarginLeft + readSkLength(stream); // fixedMarginTop + readSkLength(stream); // fixedMarginRight + readSkLength(stream); // fixedMarginBottom + readSkRect(stream); // fixedRect + stream->readS32(); // renderLayerPos.x() + stream->readS32(); // renderLayerPos.y() + } + layer->m_backfaceVisibility = stream->readBool(); layer->m_visible = stream->readBool(); layer->m_backgroundColor = stream->readU32(); @@ -404,7 +469,7 @@ LayerAndroid* deserializeLayer(SkStream* stream) } int childCount = stream->readU32(); for (int i = 0; i < childCount; i++) { - LayerAndroid *childLayer = deserializeLayer(stream); + LayerAndroid *childLayer = deserializeLayer(version, stream); if (childLayer) layer->addChild(childLayer); } @@ -419,7 +484,7 @@ LayerAndroid* deserializeLayer(SkStream* stream) static JNINativeMethod gSerializerMethods[] = { { "nativeSerializeViewState", "(ILjava/io/OutputStream;[B)Z", (void*) nativeSerializeViewState }, - { "nativeDeserializeViewState", "(Ljava/io/InputStream;[B)I", + { "nativeDeserializeViewState", "(ILjava/io/InputStream;[B)I", (void*) nativeDeserializeViewState }, }; diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index 41a8339..af25b3b 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -366,6 +366,8 @@ struct WebViewCore::JavaGlue { jmethodID m_selectAt; jmethodID m_initEditField; jmethodID m_updateMatchCount; + 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 @@ -482,6 +484,8 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V"); m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(ILjava/lang/String;IZZLjava/lang/String;IIII)V"); m_javaGlue->m_updateMatchCount = GetJMethod(env, clazz, "updateMatchCount", "(IILjava/lang/String;)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); @@ -1670,6 +1674,23 @@ void WebViewCore::selectText(int startX, int startY, int endX, int endY) 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 AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool doMoveMouse) { @@ -1711,11 +1732,7 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do 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) - || eventNode->hasEventListeners(eventNames().mouseoverEvent)) { + if (nodeIsClickableOrFocusable(eventNode)) { found = true; break; } @@ -1816,15 +1833,15 @@ AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool do } // now get the node's highlight rectangles in the page coordinate system 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); } - // Update innerNode and innerNonSharedNode - androidHitResult.hitTestResult().setInnerNode(final.mInnerNode); - androidHitResult.hitTestResult().setInnerNonSharedNode(final.mInnerNode); IntPoint frameAdjust; if (frame != m_mainFrame) { frameAdjust = frame->view()->contentsToWindow(IntPoint()); @@ -2990,6 +3007,24 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event) return eventHandler->keyEvent(event); } +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); +} + // 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) { diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index 4cbc566..c5704e0 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -29,6 +29,7 @@ #include "DeviceMotionAndOrientationManager.h" #include "DOMSelection.h" #include "FileChooser.h" +#include "FocusDirection.h" #include "HitTestResult.h" #include "PictureSet.h" #include "PlatformGraphicsContext.h" @@ -318,6 +319,8 @@ namespace android { * @return Whether keyCode was handled by this class. */ bool key(const WebCore::PlatformKeyboardEvent& event); + bool chromeCanTakeFocus(FocusDirection direction); + void chromeTakeFocus(FocusDirection direction); /** * Handle (trackball) click event / dpad center press from Java. @@ -509,6 +512,7 @@ namespace android { Node** node, HitTestResult* hitTestResult); // This does a sloppy hit test AndroidHitTestResult hitTestAtPoint(int x, int y, int slop, bool doMoveMouse = false); + static bool nodeIsClickableOrFocusable(Node* node); // Open a file chooser for selecting a file to upload void openFileChooser(PassRefPtr<WebCore::FileChooser> ); diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 830ef4e..8b7acc5 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -313,7 +313,7 @@ PictureSet* draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras, bool spli if (compositeLayer) { // call this to be sure we've adjusted for any scrolling or animations // before we actually draw - compositeLayer->updateFixedLayersPositions(m_visibleRect); + compositeLayer->updateLayerPositions(m_visibleRect); compositeLayer->updatePositions(); // We have to set the canvas' matrix on the base layer // (to have fixed layers work as intended) |
