diff options
Diffstat (limited to 'WebCore')
| -rw-r--r-- | WebCore/bindings/v8/ScriptController.cpp | 13 | ||||
| -rw-r--r-- | WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp | 216 | ||||
| -rw-r--r-- | WebCore/bridge/jni/v8/JNIUtilityPrivate.h | 6 | ||||
| -rw-r--r-- | WebCore/bridge/jni/v8/JavaNPObjectV8.cpp | 10 | ||||
| -rw-r--r-- | WebCore/bridge/npapi.h | 7 | ||||
| -rw-r--r-- | WebCore/html/HTMLPlugInElement.cpp | 7 | ||||
| -rw-r--r-- | WebCore/html/HTMLPlugInElement.h | 6 | ||||
| -rw-r--r-- | WebCore/platform/android/GeolocationServiceAndroid.cpp | 5 | ||||
| -rw-r--r-- | WebCore/platform/graphics/android/ImageSourceAndroid.cpp | 4 | ||||
| -rw-r--r-- | WebCore/platform/image-decoders/ImageDecoder.h | 5 | ||||
| -rw-r--r-- | WebCore/plugins/PluginStream.cpp | 25 | ||||
| -rw-r--r-- | WebCore/plugins/PluginStream.h | 4 | ||||
| -rw-r--r-- | WebCore/plugins/PluginView.h | 3 | ||||
| -rw-r--r-- | WebCore/plugins/android/PluginViewAndroid.cpp | 43 | ||||
| -rw-r--r-- | WebCore/rendering/RenderLayerCompositor.cpp | 57 | ||||
| -rw-r--r-- | WebCore/rendering/RenderLayerCompositor.h | 5 | ||||
| -rw-r--r-- | WebCore/rendering/RenderView.h | 3 |
17 files changed, 371 insertions, 48 deletions
diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index e2b886d..4e8ba5e 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -334,6 +334,19 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge v8::Local<v8::Object> wrapper = createV8ObjectForNPObject(npObject, 0); +#ifdef ANDROID_FIX + // TODO: this should be up streamed. + // HTMLEmbedElement::getInstance() will call this function with its closest + // ancestor who has the objectTag. So this "widget" may be already in the + // HashMap. If it does, even m_pluginObjects.set() is a no-op, we do need to + // call _NPN_ReleaseObject on the npObject to balance the reference count. + PluginObjectMap::iterator it = m_pluginObjects.find(widget); + if (it != m_pluginObjects.end()) { + ASSERT(it->second == npObject); + _NPN_ReleaseObject(it->second); + } +#endif + // Track the plugin object. We've been given a reference to the object. m_pluginObjects.set(widget, npObject); diff --git a/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp b/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp index 1bdae53..a6c4149 100644 --- a/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp +++ b/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp @@ -28,6 +28,7 @@ #include "JavaInstanceV8.h" #include "JavaNPObjectV8.h" +#include "npruntime_impl.h" namespace JSC { @@ -40,9 +41,168 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja switch (jniType) { case array_type: + { + JNIEnv* env = getJNIEnv(); + jobject javaArray; + NPObject* object = NPVARIANT_IS_OBJECT(value) ? NPVARIANT_TO_OBJECT(value) : 0; + NPVariant npvLength; + bool success = _NPN_GetProperty(0, object, _NPN_GetStringIdentifier("length"), &npvLength); + if (!success) { + // No length property so we don't know how many elements to put into the array. + // Treat this as an error. +#ifdef EMULATE_JSC_BINDINGS + // JSC sends null for an array that is not an array of strings or basic types, + // do this also in the unknown length case. + memset(&result, 0, sizeof(jvalue)); +#else + // Sending NULL as JSC does seems dangerous. (Imagine the java method that asks + // for the length of the array it was passed). Here we send a 0 length array. + jclass objectClass = env->FindClass("java/lang/Object"); + javaArray = env->NewObjectArray(0, objectClass, 0); + env->DeleteLocalRef(objectClass); +#endif + break; + } + + jsize length = static_cast<jsize>(NPVARIANT_TO_INT32(npvLength)); + + if (!strcmp(javaClassName, "[Ljava.lang.String;")) { + // Match JSC behavior by only allowing Object arrays if they are Strings. + jclass stringClass = env->FindClass("java/lang/String"); + javaArray = env->NewObjectArray(length, stringClass, 0); + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + if(NPVARIANT_IS_STRING(npvValue)) { + NPString str = NPVARIANT_TO_STRING(npvValue); + env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray), i, env->NewStringUTF(str.UTF8Characters)); + } + } + + env->DeleteLocalRef(stringClass); + } else if (!strcmp(javaClassName, "[B")) { + // array of bytes + javaArray = env->NewByteArray(length); + // Now iterate over each element and add to the array. + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + if (NPVARIANT_IS_INT32(npvValue)) { + jbyte bVal = static_cast<jbyte>(NPVARIANT_TO_INT32(npvValue)); + env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray), i, 1, &bVal); + } + } + } else if (!strcmp(javaClassName, "[C")) { + // array of chars + javaArray = env->NewCharArray(length); + // Now iterate over each element and add to the array. + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + jchar cVal = 0; + if (NPVARIANT_IS_INT32(npvValue)) { + cVal = static_cast<jchar>(NPVARIANT_TO_INT32(npvValue)); + } else if (NPVARIANT_IS_STRING(npvValue)) { + NPString str = NPVARIANT_TO_STRING(npvValue); + cVal = str.UTF8Characters[0]; + } + env->SetCharArrayRegion(static_cast<jcharArray>(javaArray), i, 1, &cVal); + } + } else if (!strcmp(javaClassName, "[D")) { + // array of doubles + javaArray = env->NewDoubleArray(length); + // Now iterate over each element and add to the array. + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + if (NPVARIANT_IS_DOUBLE(npvValue)) { + jdouble dVal = NPVARIANT_TO_DOUBLE(npvValue); + env->SetDoubleArrayRegion(static_cast<jdoubleArray>(javaArray), i, 1, &dVal); + } + } + } else if (!strcmp(javaClassName, "[F")) { + // array of floats + javaArray = env->NewFloatArray(length); + // Now iterate over each element and add to the array. + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + if (NPVARIANT_IS_DOUBLE(npvValue)) { + jfloat fVal = static_cast<jfloat>(NPVARIANT_TO_DOUBLE(npvValue)); + env->SetFloatArrayRegion(static_cast<jfloatArray>(javaArray), i, 1, &fVal); + } + } + } else if (!strcmp(javaClassName, "[I")) { + // array of ints + javaArray = env->NewIntArray(length); + // Now iterate over each element and add to the array. + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + if (NPVARIANT_IS_INT32(npvValue)) { + jint iVal = NPVARIANT_TO_INT32(npvValue); + env->SetIntArrayRegion(static_cast<jintArray>(javaArray), i, 1, &iVal); + } + } + } else if (!strcmp(javaClassName, "[J")) { + // array of longs + javaArray = env->NewLongArray(length); + // Now iterate over each element and add to the array. + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + if (NPVARIANT_IS_INT32(npvValue)) { + jlong jVal = static_cast<jlong>(NPVARIANT_TO_INT32(npvValue)); + env->SetLongArrayRegion(static_cast<jlongArray>(javaArray), i, 1, &jVal); + } + } + } else if (!strcmp(javaClassName, "[S")) { + // array of shorts + javaArray = env->NewShortArray(length); + // Now iterate over each element and add to the array. + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + if (NPVARIANT_IS_INT32(npvValue)) { + jshort sVal = static_cast<jshort>(NPVARIANT_TO_INT32(npvValue)); + env->SetShortArrayRegion(static_cast<jshortArray>(javaArray), i, 1, &sVal); + } + } + } else if (!strcmp(javaClassName, "[Z")) { + // array of booleans + javaArray = env->NewBooleanArray(length); + // Now iterate over each element and add to the array. + for (jsize i = 0; i < length; i++) { + NPVariant npvValue; + _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue); + if (NPVARIANT_IS_BOOLEAN(npvValue)) { + jboolean zVal = NPVARIANT_TO_BOOLEAN(npvValue); + env->SetBooleanArrayRegion(static_cast<jbooleanArray>(javaArray), i, 1, &zVal); + } + } + } else { +#ifdef EMULATE_JSC_BINDINGS + // JSC sends null for an array that is not an array of strings or basic types. + memset(&result, 0, sizeof(jvalue)); + break; +#else + // Sending NULL as JSC does seems dangerous. (Imagine the java method that asks + // for the length of the array it was passed). Here we send a 0 length array. + jclass objectClass = env->FindClass("java/lang/Object"); + javaArray = env->NewObjectArray(0, objectClass, 0); + env->DeleteLocalRef(objectClass); +#endif + } + + result.l = javaArray; + } + break; + case object_type: { + JNIEnv* env = getJNIEnv(); result.l = static_cast<jobject>(0); + jobject javaString; // First see if we have a Java instance. if (type == NPVariantType_Object) { @@ -56,7 +216,6 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja if (!result.l && !strcmp(javaClassName, "java.lang.String")) { #ifdef CONVERT_NULL_TO_EMPTY_STRING if (type == NPVariantType_Null) { - JNIEnv* env = getJNIEnv(); jchar buf[2]; jobject javaString = env->functions->NewString(env, buf, 0); result.l = javaString; @@ -66,10 +225,38 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja #endif { NPString src = NPVARIANT_TO_STRING(value); - JNIEnv* env = getJNIEnv(); - jobject javaString = env->NewStringUTF(src.UTF8Characters); + javaString = env->NewStringUTF(src.UTF8Characters); + result.l = javaString; + } else if (type == NPVariantType_Int32) { + jint src = NPVARIANT_TO_INT32(value); + jclass integerClass = env->FindClass("java/lang/Integer"); + jmethodID toString = env->GetStaticMethodID(integerClass, "toString", "(I)Ljava/lang/String;"); + javaString = env->CallStaticObjectMethod(integerClass, toString, src); + result.l = javaString; + env->DeleteLocalRef(integerClass); + } else if (type == NPVariantType_Bool) { + jboolean src = NPVARIANT_TO_BOOLEAN(value); + jclass booleanClass = env->FindClass("java/lang/Boolean"); + jmethodID toString = env->GetStaticMethodID(booleanClass, "toString", "(Z)Ljava/lang/String;"); + javaString = env->CallStaticObjectMethod(booleanClass, toString, src); + result.l = javaString; + env->DeleteLocalRef(booleanClass); + } else if (type == NPVariantType_Double) { + jdouble src = NPVARIANT_TO_DOUBLE(value); + jclass doubleClass = env->FindClass("java/lang/Double"); + jmethodID toString = env->GetStaticMethodID(doubleClass, "toString", "(D)Ljava/lang/String;"); + javaString = env->CallStaticObjectMethod(doubleClass, toString, src); result.l = javaString; + env->DeleteLocalRef(doubleClass); } +#ifdef EMULATE_JSC_BINDINGS + // For the undefined value, JSC sends the String "undefined". Feels to me like we + // should send null in this case. + else if (!NPVARIANT_IS_NULL(value)) { + javaString = env->NewStringUTF("undefined"); + result.l = javaString; + } +#endif } else if (!result.l) memset(&result, 0, sizeof(jvalue)); // Handle it the same as a void case } @@ -97,6 +284,15 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja { if (type == NPVariantType_Int32) result.c = static_cast<char>(NPVARIANT_TO_INT32(value)); +#ifndef EMULATE_JSC_BINDINGS + // There is no char type in JavaScript - just strings 1 character + // long. So just converting it to an int above doesn't work. Again, + // we emulate the behavior for now for maximum compatability. + else if (type == NPVariantType_String) { + NPString str = NPVARIANT_TO_STRING(value); + result.c = str.UTF8Characters[0]; + } +#endif else memset(&result, 0, sizeof(jvalue)); } @@ -153,8 +349,6 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja } break; - break; - case invalid_type: default: case void_type: @@ -206,7 +400,17 @@ void convertJValueToNPVariant(jvalue value, JNIType jniType, const char* javaTyp case char_type: { - INT32_TO_NPVARIANT(value.c, *result); +#ifndef EMULATE_JSC_BINDINGS + // There is no char type in JavaScript - just strings 1 character + // long. So just converting it to an int above doesn't work. Again, + // we emulate the behavior for now for maximum compatability. + if (!strcmp(javaTypeName, "char")) { + const char c = value.c; + const char* v = strndup(&c, 1); + STRINGZ_TO_NPVARIANT(v, *result); + } else +#endif + INT32_TO_NPVARIANT(value.c, *result); } break; diff --git a/WebCore/bridge/jni/v8/JNIUtilityPrivate.h b/WebCore/bridge/jni/v8/JNIUtilityPrivate.h index 951c1e8..da7a24c 100644 --- a/WebCore/bridge/jni/v8/JNIUtilityPrivate.h +++ b/WebCore/bridge/jni/v8/JNIUtilityPrivate.h @@ -29,6 +29,12 @@ #include "JNIUtility.h" #include "npruntime.h" +// FIXME: While fully implementing the bindings I noticed some differences between what +// I wrote and seemed intuitive and what JSC does. Need to verify if my intuition is wrong +// or there are bugs in the JSC bindings. For now, this macro makes the V8 bindings do the +// same as the JSC bindings. +#define EMULATE_JSC_BINDINGS 1 + namespace JSC { namespace Bindings { diff --git a/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp b/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp index 54cb8d6..88e28d4 100644 --- a/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp +++ b/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp @@ -155,11 +155,19 @@ bool JavaNPObjectGetProperty(NPObject* obj, NPIdentifier identifier, NPVariant* if (!field) return false; +#ifdef EMULATE_JSC_BINDINGS + // JSC does not seem to support returning object properties so we emulate that + // behaviour here. + jvalue value; +#else + // FIXME: Note here that field->type() refers to the Java class name and NOT the + // JNI signature i.e. "int" as opposed to "I". This means that the field lookup + // will fail. jvalue value = getJNIField(instance->javaInstance(), field->getJNIType(), field->name().UTF8String(), field->type()); - +#endif convertJValueToNPVariant(value, field->getJNIType(), field->type(), result); return true; diff --git a/WebCore/bridge/npapi.h b/WebCore/bridge/npapi.h index 41f9bda..351b414 100644 --- a/WebCore/bridge/npapi.h +++ b/WebCore/bridge/npapi.h @@ -375,7 +375,12 @@ typedef enum { #endif #ifdef ANDROID - // TODO(andreip): Remove? + /* Used when the plugin returns 0 from NPN_WriteReady and wishes the browser + * to wait a certain amount of millis before calling NPN_WriteReady again. + */ + NPPDataDeliveryDelayMs = 100, + + // TODO(reed): upstream NPPFakeValueToForce32Bits = 0x7FFFFFFF #endif } NPPVariable; diff --git a/WebCore/html/HTMLPlugInElement.cpp b/WebCore/html/HTMLPlugInElement.cpp index dafa8fb..9319034 100644 --- a/WebCore/html/HTMLPlugInElement.cpp +++ b/WebCore/html/HTMLPlugInElement.cpp @@ -177,4 +177,11 @@ void HTMLPlugInElement::updateWidgetCallback(Node* n) static_cast<HTMLPlugInElement*>(n)->updateWidget(); } +#if PLATFORM(ANDROID) +bool HTMLPlugInElement::supportsFocus() const +{ + return true; +} +#endif + } diff --git a/WebCore/html/HTMLPlugInElement.h b/WebCore/html/HTMLPlugInElement.h index 9d3dc6d..cf18e27 100644 --- a/WebCore/html/HTMLPlugInElement.h +++ b/WebCore/html/HTMLPlugInElement.h @@ -60,6 +60,12 @@ protected: virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const; virtual void parseMappedAttribute(MappedAttribute*); +#if PLATFORM(ANDROID) + // in Android, plugin has a focused mode where it accepts all the touch events. + // so need to claim that plugin element supports focus instead of using the default. + virtual bool supportsFocus() const; +#endif + private: virtual void defaultEventHandler(Event*); diff --git a/WebCore/platform/android/GeolocationServiceAndroid.cpp b/WebCore/platform/android/GeolocationServiceAndroid.cpp index 61043fb..7f7d58e 100644 --- a/WebCore/platform/android/GeolocationServiceAndroid.cpp +++ b/WebCore/platform/android/GeolocationServiceAndroid.cpp @@ -111,6 +111,9 @@ void GeolocationServiceAndroid::stopUpdating() // new position from the system service when a request is first made. m_lastPosition = 0; m_lastError = 0; + // remove the pending timer + if (m_timer.isActive()) + m_timer.stop(); } void GeolocationServiceAndroid::suspend() @@ -155,7 +158,7 @@ void GeolocationServiceAndroid::timerFired(Timer<GeolocationServiceAndroid>* tim ASSERT(m_lastPosition || m_lastError); if (m_lastPosition) positionChanged(); - else + else if (m_lastError) errorOccurred(); } diff --git a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp index fa1794c..06455d2 100644 --- a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp +++ b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp @@ -215,8 +215,12 @@ void ImageSource::setURL(const String& url) // we only animate small GIFs for now, to save memory // also, we only support this in Japan, hence the Emoji check static bool should_use_animated_gif(int width, int height) { +#ifdef ANDROID_LARGE_MEMORY_DEVICE + return true; +#else return EmojiFont::IsAvailable() && width <= 32 && height <= 32; +#endif } #endif diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h index 3ca7abf..8d27072 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.h +++ b/WebCore/platform/image-decoders/ImageDecoder.h @@ -39,6 +39,7 @@ #if PLATFORM(SKIA) #include "NativeImageSkia.h" +#include "SkColorPriv.h" #elif PLATFORM(QT) #include <QImage> #endif @@ -169,7 +170,11 @@ namespace WebCore { g = static_cast<unsigned>(g * alphaPercent); b = static_cast<unsigned>(b * alphaPercent); } +#if PLATFORM(ANDROID) + *dest = SkPackARGB32(a, r, g, b); +#else *dest = (a << 24 | r << 16 | g << 8 | b); +#endif } } diff --git a/WebCore/plugins/PluginStream.cpp b/WebCore/plugins/PluginStream.cpp index 1e91c51..9341c15 100644 --- a/WebCore/plugins/PluginStream.cpp +++ b/WebCore/plugins/PluginStream.cpp @@ -349,8 +349,13 @@ void PluginStream::deliverData() // TODO: This needs to be upstreamed. if (m_loader) m_loader->pauseLoad(true); -#endif + + // ask the plugin for a delay value. + int delay = deliveryDelay(); + m_delayDeliveryTimer.startOneShot(delay * 0.001); +#else m_delayDeliveryTimer.startOneShot(0); +#endif break; } else { deliveryBytes = min(deliveryBytes, totalBytes - totalBytesDelivered); @@ -436,6 +441,10 @@ void PluginStream::didReceiveData(NetscapePlugInStreamLoader* loader, const char m_deliveryData->resize(oldSize + length); memcpy(m_deliveryData->data() + oldSize, data, length); +#if PLATFORM(ANDROID) +//TODO: This needs to be upstreamed to WebKit. + if (!m_delayDeliveryTimer.isActive()) +#endif deliverData(); } @@ -485,4 +494,18 @@ bool PluginStream::wantsAllStreams() const return result != 0; } +#if PLATFORM(ANDROID) +int PluginStream::deliveryDelay() const +{ + if (!m_pluginFuncs->getvalue) + return 0; + + int delay = 0; + if (m_pluginFuncs->getvalue(m_instance, NPPDataDeliveryDelayMs, &delay) != NPERR_NO_ERROR) + return 0; + + return delay; +} +#endif + } diff --git a/WebCore/plugins/PluginStream.h b/WebCore/plugins/PluginStream.h index dc08f01..29a2644 100644 --- a/WebCore/plugins/PluginStream.h +++ b/WebCore/plugins/PluginStream.h @@ -88,7 +88,9 @@ namespace WebCore { void deliverData(); void destroyStream(NPReason); void destroyStream(); - +#if PLATFORM(ANDROID) + int deliveryDelay() const; +#endif ResourceRequest m_resourceRequest; ResourceResponse m_resourceResponse; diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h index 41e563c..f14eb3d 100644 --- a/WebCore/plugins/PluginView.h +++ b/WebCore/plugins/PluginView.h @@ -410,6 +410,9 @@ private: IntRect m_clipRect; // The clip rect to apply to a windowed plug-in IntRect m_windowRect; // Our window rect. +#ifdef ANDROID_PLUGINS + IntRect m_pageRect; // The rect in page coordinate system. +#endif bool m_loadManually; RefPtr<PluginStream> m_manualStream; diff --git a/WebCore/plugins/android/PluginViewAndroid.cpp b/WebCore/plugins/android/PluginViewAndroid.cpp index 452c9fb..682268a 100644 --- a/WebCore/plugins/android/PluginViewAndroid.cpp +++ b/WebCore/plugins/android/PluginViewAndroid.cpp @@ -247,11 +247,9 @@ void PluginView::handleMouseEvent(MouseEvent* event) evt.data.mouse.y = localPos.y(); if (isDown) { - // The plugin needs focus to receive keyboard events - if (Page* page = m_parentFrame->page()) { - page->focusController()->setFocusedNode(m_element, m_parentFrame); - event->setDefaultHandled(); - } + // The plugin needs focus to receive keyboard and touch events + m_element->focus(); + event->setDefaultHandled(); } } else { @@ -427,23 +425,17 @@ void PluginView::setNPWindowIfNeeded() return; // in Android, plugin always get the setwindow() in the page coordinate. - IntRect pageRect = m_windowRect; - ScrollView* top = parent(); - while (top->parent()) - top = top->parent(); - // only the top ScrollView can have the offset - pageRect.move(top->scrollOffset()); // the m_npWindow is relative to the page - m_npWindow.x = pageRect.x(); - m_npWindow.y = pageRect.y(); - m_npWindow.width = pageRect.width(); - m_npWindow.height = pageRect.height(); + m_npWindow.x = m_pageRect.x(); + m_npWindow.y = m_pageRect.y(); + m_npWindow.width = m_pageRect.width(); + m_npWindow.height = m_pageRect.height(); - m_npWindow.clipRect.left = pageRect.x(); - m_npWindow.clipRect.top = pageRect.y(); - m_npWindow.clipRect.right = pageRect.x() + pageRect.width(); - m_npWindow.clipRect.bottom = pageRect.y() + pageRect.height(); + m_npWindow.clipRect.left = m_pageRect.x(); + m_npWindow.clipRect.top = m_pageRect.y(); + m_npWindow.clipRect.right = m_pageRect.x() + m_pageRect.width(); + m_npWindow.clipRect.bottom = m_pageRect.y() + m_pageRect.height(); if (m_plugin->pluginFuncs()->setwindow) { #if USE(JSC) @@ -666,11 +658,18 @@ void PluginView::updatePluginWidget() FrameView* frameView = static_cast<FrameView*>(parent()); PLUGIN_LOG("--%p UpdatePluginWidget frame=[%p] \n", instance(), frameView); if (frameView) { - IntRect oldWindowRect = m_windowRect; - m_windowRect = frameView->contentsToWindow(frameRect()); - if (m_windowRect != oldWindowRect) + IntRect oldPageRect = m_pageRect; + + // only the top ScrollView can have the offset + m_pageRect = m_windowRect; + ScrollView* top = parent(); + while (top->parent()) + top = top->parent(); + m_pageRect.move(top->scrollOffset()); + + if (m_pageRect != oldPageRect) setNPWindowIfNeeded(); } } diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index e8d476b..22118fe 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -982,14 +982,49 @@ bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers(); } +#if PLATFORM(ANDROID) +bool RenderLayerCompositor::requiresCompositingForMobileSites(const RenderLayer* layer) const +{ + // First, check if we are in an iframe, and if so bail out + if (m_renderView->document()->frame()->tree()->parent()) + return false; + + RenderObject* renderer = layer->renderer(); + // Check for transforms + if (requiresCompositingForTransform(renderer)) + return true; + + // Check for animations + if (requiresCompositingForAnimation(renderer)) + return true; + +#if ENABLE(COMPOSITED_FIXED_ELEMENTS) + // For the moment, we want to only enable fixed composited layers on mobile websites. + // We can consider a website as being a 'mobile' site if all the + // following checks are true: + // 1) - the viewport width is either undefined (-1) or equal to device-width (0), and + // 2) - no scaling is allowed + if (!layer->isFixed()) + return false; + + Settings* settings = m_renderView->document()->settings(); + if (!settings) + return false; + + if ((settings->viewportWidth() == -1 || settings->viewportWidth() == 0) && + !settings->viewportUserScalable()) + return true; +#endif + + return false; +} +#endif + // Note: this specifies whether the RL needs a compositing layer for intrinsic reasons. // Use needsToBeComposited() to determine if a RL actually needs a compositing layer. // static bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const { -#if ENABLE(COMPOSITED_FIXED_ELEMENTS) - Settings* settings = m_renderView->document()->settings(); -#endif RenderObject* renderer = layer->renderer(); // The compositing state of a reflection should match that of its reflected layer. if (layer->isReflection()) { @@ -998,25 +1033,17 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c } // The root layer always has a compositing layer, but it may not have backing. return (inCompositingMode() && layer->isRootLayer()) || - requiresCompositingForTransform(renderer) || #if PLATFORM(ANDROID) -#if ENABLE(COMPOSITED_FIXED_ELEMENTS) - // For the moment, we want to only enable fixed composited layers on mobile websites. - // We can consider a website as being a 'mobile' site if all the - // following checks are true: - // 1) - the viewport width is either undefined (-1) or equal to device-width (0), and - // 2) - no scaling is allowed - (((settings->viewportWidth() == -1) || (settings->viewportWidth() == 0)) && - !settings->viewportUserScalable() && layer->isFixed()) || -#endif + requiresCompositingForMobileSites(layer) || #else + requiresCompositingForTransform(renderer) || requiresCompositingForVideo(renderer) || requiresCompositingForCanvas(renderer) || requiresCompositingForPlugin(renderer) || + requiresCompositingForAnimation(renderer) || #endif renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden || - clipsCompositingDescendants(layer) || - requiresCompositingForAnimation(renderer); + clipsCompositingDescendants(layer); } // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips, diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index 5f1a178..eeacdf7 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -181,6 +181,11 @@ private: bool requiresCompositingForPlugin(RenderObject*) const; bool requiresCompositingWhenDescendantsAreCompositing(RenderObject*) const; +#if PLATFORM(ANDROID) + // Whether we are on a mobile site + bool requiresCompositingForMobileSites(const RenderLayer* layer) const; +#endif + private: RenderView* m_renderView; OwnPtr<GraphicsLayer> m_rootPlatformLayer; diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h index c287579..faa2465 100644 --- a/WebCore/rendering/RenderView.h +++ b/WebCore/rendering/RenderView.h @@ -105,6 +105,9 @@ public: void updateWidgetPositions(); void addWidget(RenderWidget*); void removeWidget(RenderWidget*); +#ifdef ANDROID_PLUGINS + const HashSet<RenderWidget*>& widgets() const { return m_widgets; } +#endif // layoutDelta is used transiently during layout to store how far an object has moved from its // last layout location, in order to repaint correctly. |
