android/plugins/ANPPathInterface.cpp \
android/plugins/ANPSoundInterface.cpp \
android/plugins/ANPSurfaceInterface.cpp \
- android/plugins/ANPTypefaceInterface.cpp \
+ android/plugins/ANPTypefaceInterface.cpp \
android/plugins/ANPWindowInterface.cpp \
+ android/plugins/PluginSurface.cpp \
android/plugins/PluginTimer.cpp \
android/plugins/PluginViewBridgeAndroid.cpp \
android/plugins/PluginWidgetAndroid.cpp \
#include "SkCanvas.h"
#include "SkPicture.h"
#include "SkUtils.h"
+#include "SurfaceCallback.h"
#include "StringImpl.h"
#include "Text.h"
#include "TypingCommand.h"
jmethodID m_requestKeyboard;
jmethodID m_exceededDatabaseQuota;
jmethodID m_addMessageToConsole;
+ jmethodID m_createSurface;
+ jmethodID m_destroySurface;
+ jmethodID m_attachSurface;
AutoJObject object(JNIEnv* env) {
return getRealObject(env, m_obj);
}
m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V");
m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;J)V");
m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;)V");
+ m_javaGlue->m_createSurface = GetJMethod(env, clazz, "createSurface", "(I)Landroid/view/SurfaceView;");
+ m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/view/SurfaceView;)V");
+ m_javaGlue->m_attachSurface = GetJMethod(env, clazz, "attachSurface", "(Landroid/view/SurfaceView;IIII)V");
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
view->setBaseBackgroundColor(bcolor);
}
+jobject WebViewCore::createSurface(SurfaceCallback* cb)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ jobject surface = env->CallObjectMethod(m_javaGlue->object(env).get(),
+ m_javaGlue->m_createSurface, (int) cb);
+ checkException(env);
+ return surface;
+}
+
+void WebViewCore::destroySurface(jobject surface)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(),
+ m_javaGlue->m_destroySurface, surface);
+ checkException(env);
+}
+
+void WebViewCore::attachSurface(jobject surface, int x, int y, int width,
+ int height)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(),
+ m_javaGlue->m_attachSurface, surface, x, y, width, height);
+ checkException(env);
+}
+
//----------------------------------------------------------------------
// Native JNI methods
//----------------------------------------------------------------------
(PluginState) state);
}
+static void SurfaceChanged(JNIEnv* env, jobject obj, jint pointer, jint state,
+ jint format, jint width, jint height)
+{
+ // Be safe and check for a valid callback
+ if (!pointer)
+ return;
+ SurfaceCallback* cb = reinterpret_cast<SurfaceCallback*>(pointer);
+ switch (state) {
+ case 0:
+ cb->surfaceCreated();
+ break;
+ case 1:
+ cb->surfaceChanged(format, width, height);
+ break;
+ case 2:
+ cb->surfaceDestroyed();
+ break;
+ default:
+ break;
+ }
+}
+
static void Pause(JNIEnv* env, jobject obj)
{
ANPEvent event;
(void*) DumpNavTree },
{ "nativeSetDatabaseQuota", "(J)V",
(void*) SetDatabaseQuota },
+ { "nativeSurfaceChanged", "(IIIII)V",
+ (void*) SurfaceChanged },
{ "nativePause", "()V", (void*) Pause },
{ "nativeResume", "()V", (void*) Resume },
{ "nativeFreeMemory", "()V", (void*) FreeMemory },
class CachedRoot;
class ListBoxReply;
+ class SurfaceCallback;
class WebCoreReply : public WebCoreRefObject {
public:
// Notify the Java side that webkit is requesting a keyboard
void requestKeyboard(bool);
+ // Creates a SurfaceView for a plugin
+ jobject createSurface(SurfaceCallback* cb);
+
+ // Destroys the SurfaceView after removing from the view system.
+ void destroySurface(jobject surface);
+
+ // Positions the SurfaceView at x,y with dimensions width x height
+ void attachSurface(jobject surface, int x, int y, int width, int height);
+
// other public functions
public:
// reset the picture set to empty
// must include config.h first for webkit to fiddle with new/delete
#include "config.h"
+
+#include "PluginSurface.h"
+#include "PluginView.h"
+#include "PluginWidgetAndroid.h"
#include "SkANP.h"
-static ANPSurface* anp_newSurface(NPP instance, ANPSurfaceType) {
+using namespace WebCore;
+
+static ANPSurface* anp_newSurface(NPP instance, ANPSurfaceType type) {
+ if (instance && instance->ndata) {
+ PluginView* view = static_cast<PluginView*>(instance->ndata);
+ PluginWidgetAndroid* widget = view->platformPluginWidget();
+ return widget->createSurface(type);
+ }
return NULL;
}
static void anp_deleteSurface(ANPSurface* surface) {
-
+ if (surface) {
+ if (surface->data) {
+ android::PluginSurface* s =
+ static_cast<android::PluginSurface*>(surface->data);
+ s->destroy();
+ }
+ delete surface;
+ }
}
static bool anp_lock(ANPSurface* surface, ANPBitmap* bitmap,
ANPRectI* dirtyRect) {
+ if (bitmap && surface && surface->data) {
+ android::PluginSurface* s =
+ static_cast<android::PluginSurface*>(surface->data);
+ SkBitmap src;
+ bool res = false;
+ if (dirtyRect) {
+ SkIRect rect;
+ res = s->lock(SkANP::SetRect(&rect, *dirtyRect), &src);
+ } else {
+ res = s->lock(NULL, &src);
+ }
+ if (res) {
+ res &= SkANP::SetBitmap(bitmap, src);
+ }
+ return res;
+ }
return false;
}
static void anp_unlock(ANPSurface* surface) {
-
+ if (surface && surface->data) {
+ android::PluginSurface* s =
+ static_cast<android::PluginSurface*>(surface->data);
+ s->unlock();
+ }
}
///////////////////////////////////////////////////////////////////////////////
--- /dev/null
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "PluginSurface.h"
+
+#include "android_graphics.h"
+#include "PluginWidgetAndroid.h"
+#include "WebViewCore.h"
+#include "jni_utility.h"
+
+#include <ui/Rect.h>
+#include <ui/Region.h>
+#include <ui/Surface.h>
+
+namespace android {
+
+// jni field offset for the native surface pointer.
+static jfieldID gSurfaceField;
+static jmethodID gGetHolder;
+static jmethodID gGetSurface;
+
+static void initFields(JNIEnv* env) {
+ if (gSurfaceField)
+ return;
+
+ jclass clazz = env->FindClass("android/view/Surface");
+ gSurfaceField = env->GetFieldID(clazz, "mSurface", "I");
+
+ clazz = env->FindClass("android/view/SurfaceView");
+ gGetHolder = env->GetMethodID(clazz, "getHolder", "()Landroid/view/SurfaceHolder;");
+
+ clazz = env->FindClass("android/view/SurfaceHolder");
+ gGetSurface = env->GetMethodID(clazz, "getSurface", "()Landroid/view/Surface;");
+}
+
+static inline sp<Surface> getSurface(jobject view) {
+ if (!view) {
+ return NULL;
+ }
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ initFields(env);
+ jobject holder = env->CallObjectMethod(view, gGetHolder);
+ jobject surface = env->CallObjectMethod(holder, gGetSurface);
+ return sp<Surface>((Surface*) env->GetIntField(surface, gSurfaceField));
+}
+
+static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
+ switch (format) {
+ case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config;
+ case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config;
+ case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config;
+ case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config;
+ default: return SkBitmap::kNo_Config;
+ }
+}
+
+PluginSurface::PluginSurface(PluginWidgetAndroid* widget)
+ : m_jSurfaceView(0)
+ , m_widget(widget) {
+ // Create our java SurfaceView.
+ jobject obj = widget->webViewCore()->createSurface(this);
+ if (obj) {
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ m_jSurfaceView = env->NewGlobalRef(obj);
+ env->DeleteLocalRef(obj);
+ }
+}
+
+void PluginSurface::attach(int x, int y, int width, int height) {
+ if (m_jSurfaceView) {
+ m_widget->webViewCore()->attachSurface(m_jSurfaceView, x, y, width,
+ height);
+ }
+}
+
+void PluginSurface::destroy() {
+ m_surface.clear();
+ if (m_jSurfaceView) {
+ m_widget->webViewCore()->destroySurface(m_jSurfaceView);
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->DeleteGlobalRef(m_jSurfaceView);
+ m_jSurfaceView = 0;
+ }
+}
+
+bool PluginSurface::lock(SkIRect* dirty, SkBitmap* bitmap) {
+ if (!bitmap || !Surface::isValid(m_surface)) {
+ return false;
+ }
+
+ Region dirtyRegion;
+ if (dirty) {
+ Rect rect(dirty->fLeft, dirty->fTop, dirty->fRight, dirty->fBottom);
+ if (!rect.isEmpty()) {
+ dirtyRegion.set(rect);
+ }
+ } else {
+ dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
+ }
+
+ Surface::SurfaceInfo info;
+ status_t err = m_surface->lock(&info, &dirtyRegion);
+ if (err < 0) {
+ return false;
+ }
+
+ ssize_t bpr = info.s * bytesPerPixel(info.format);
+ bitmap->setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
+ if (info.w > 0 && info.h > 0) {
+ bitmap->setPixels(info.bits);
+ } else {
+ bitmap->setPixels(NULL);
+ }
+
+ return true;
+}
+
+void PluginSurface::unlock() {
+ if (!Surface::isValid(m_surface)) {
+ return;
+ }
+
+ m_surface->unlockAndPost();
+}
+
+static void sendSurfaceEvent(PluginWidgetAndroid* widget,
+ ANPSurfaceAction action, int format = 0, int width = 0,
+ int height = 0) {
+ ANPEvent event;
+ SkANP::InitEvent(&event, kSurface_ANPEventType);
+
+ event.data.surface.action = action;
+ if (action == kChanged_ANPSurfaceAction) {
+ event.data.surface.data.changed.format = format;
+ event.data.surface.data.changed.width = width;
+ event.data.surface.data.changed.height = height;
+ }
+
+ widget->sendEvent(event);
+}
+
+// SurfaceCallback methods
+void PluginSurface::surfaceCreated() {
+ m_surface = getSurface(m_jSurfaceView);
+ // Not sure what values for format, width, and height should be here.
+ sendSurfaceEvent(m_widget, kCreated_ANPSurfaceAction);
+}
+
+void PluginSurface::surfaceChanged(int format, int width, int height) {
+ m_surface = getSurface(m_jSurfaceView);
+ sendSurfaceEvent(m_widget, kChanged_ANPSurfaceAction, format, width,
+ height);
+}
+
+void PluginSurface::surfaceDestroyed() {
+ m_surface = getSurface(m_jSurfaceView);
+ // Not sure what values for format, width, and height should be here.
+ sendSurfaceEvent(m_widget, kDestroyed_ANPSurfaceAction);
+}
+
+} // namespace android
--- /dev/null
+/*
+ * Copyright 2009, The Android Open Source Project
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PluginSurface_H
+#define PluginSurface_H
+
+#include "android_npapi.h"
+#include "SkANP.h"
+#include "SurfaceCallback.h"
+
+#include <jni.h>
+#include <ui/Surface.h>
+#include <utils/RefBase.h>
+
+struct PluginWidgetAndroid;
+class SkBitmap;
+struct SkIRect;
+
+struct ANPSurface {
+ void* data;
+ ANPSurfaceType type;
+};
+
+namespace android {
+
+class Surface;
+
+class PluginSurface : public SurfaceCallback {
+public:
+ PluginSurface(PluginWidgetAndroid* widget);
+ virtual ~PluginSurface() {
+ destroy();
+ }
+
+ void attach(int x, int y, int width, int height);
+ void destroy();
+ bool lock(SkIRect* dirty, SkBitmap* bitmap);
+ void unlock();
+
+ virtual void surfaceCreated();
+ virtual void surfaceChanged(int format, int width, int height);
+ virtual void surfaceDestroyed();
+
+private:
+ jobject m_jSurfaceView;
+ sp<Surface> m_surface;
+ PluginWidgetAndroid* m_widget;
+};
+
+} // namespace android
+
+#endif
#include "Element.h"
#include "Frame.h"
#include "PluginPackage.h"
+#include "PluginSurface.h"
#include "PluginView.h"
#include "PluginWidgetAndroid.h"
#include "SkANP.h"
bool isTransparent) {
m_x = x;
m_y = y;
- m_flipPixelRef->safeUnref();
- m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent),
- width, height);
+
+ if (m_drawingModel == kSurface_ANPDrawingModel) {
+ if (m_surface) {
+ m_surface->attach(x, y, width, height);
+ }
+ } else {
+ m_flipPixelRef->safeUnref();
+ m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent),
+ width, height);
+ }
}
bool PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) {
void PluginWidgetAndroid::inval(const WebCore::IntRect& rect,
bool signalRedraw) {
- // nothing to do if we haven't had setWindow() called yet
+ // nothing to do if we haven't had setWindow() called yet. m_flipPixelRef
+ // will also be null if this is a Surface model.
if (NULL == m_flipPixelRef) {
return;
}
bool PluginWidgetAndroid::isAcceptingEvent(ANPEventFlag flag) {
return m_eventFlags & flag;
}
+
+ANPSurface* PluginWidgetAndroid::createSurface(ANPSurfaceType ignored) {
+ if (m_drawingModel != kSurface_ANPDrawingModel) {
+ return NULL;
+ }
+ m_surface.set(new android::PluginSurface(this));
+ ANPSurface* surface = new ANPSurface;
+ surface->data = m_surface.get();
+ surface->type = ignored;
+ return surface;
+}
#include "android_npapi.h"
+#include <wtf/OwnPtr.h>
+
namespace WebCore {
class PluginView;
}
namespace android {
+ class PluginSurface;
class WebViewCore;
}
WebCore::PluginView* pluginView() const { return m_pluginView; }
+ // Needed by PluginSurface to manage the java SurfaceView.
+ android::WebViewCore* webViewCore() const { return m_core; }
+
/* Can't determine our core at construction time, so PluginView calls this
as soon as it has a parent.
*/
*/
bool isAcceptingEvent(ANPEventFlag);
+ /* Create an ANPSurface that the plugin may draw in to. The drawing model
+ must be kSurface_ANPDrawingModel for this call to succeed. The type
+ specifies what kind of pixel access will be available.
+ */
+ ANPSurface* createSurface(ANPSurfaceType type);
+
private:
WebCore::PluginView* m_pluginView;
android::WebViewCore* m_core;
ANPEventFlags m_eventFlags;
int m_x;
int m_y;
+ OwnPtr<android::PluginSurface> m_surface;
};
#endif
--- /dev/null
+/*
+ * Copyright 2009, The Android Open Source Project
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SurfaceCallback_H
+#define SurfaceCallback_H
+
+namespace android {
+
+ class SurfaceCallback {
+ public:
+ virtual ~SurfaceCallback() {}
+ virtual void surfaceCreated() = 0;
+ virtual void surfaceChanged(int format, int width, int height) = 0;
+ virtual void surfaceDestroyed() = 0;
+ };
+
+} // namespace android
+
+#endif
bool (*getPixelPacking)(ANPBitmapFormat, ANPPixelPacking* packing);
};
-/** The ANPSurface acts as a handle between the plugin and the native libraries
- that render the surface to the screen.
- */
-struct ANPSurface;
-
/** The surfaceType is the mechanism by which the plugin informs the native
libraries which type of surface view it wishes to use.
*/
};
typedef int32_t ANPSurfaceType;
+/** The ANPSurface acts as a handle between the plugin and the native libraries
+ that render the surface to the screen.
+ */
+struct ANPSurface;
+
struct ANPSurfaceInterfaceV0 : ANPInterface {
/** Creates a new surface handle based on the given surface type. If the
given surface type is not supported then NULL is returned.
kDraw_ANPEventType = 4,
kLifecycle_ANPEventType = 5,
kVisibleRect_ANPEventType = 6,
+ kSurface_ANPEventType = 7,
};
typedef int32_t ANPEventType;
};
typedef uint32_t ANPLifecycleAction;
+enum ANPSurfaceActions {
+ /** The surface has been created and is ready to be used. Any calls to
+ lock/unlock before this action will fail.
+ */
+ kCreated_ANPSurfaceAction = 0,
+ /** The surface has changed format or dimensions.
+ */
+ kChanged_ANPSurfaceAction = 1,
+ /** The surface has been destroyed. This happens when the view system has
+ remove the surface (possibly due to the plugin being offscreen). Calls
+ to lock/unlock will fail after this action and before
+ kCreate_ANPSurfaceAction.
+ */
+ kDestroyed_ANPSurfaceAction = 2,
+};
+typedef uint32_t ANPSurfaceAction;
+
/* This is what is passed to NPP_HandleEvent() */
struct ANPEvent {
uint32_t inSize; // size of this struct in bytes
ANPRectI rect; // in global document coordinates
float zoomScale; // 1.0 means no zoom scale
} visibleRect;
+ struct {
+ ANPSurfaceAction action;
+ /** This union is based on the value of action and contains data
+ specific to the given action.
+ */
+ union {
+ /** This struct is filled in only during the
+ kChanged_ANPSurfaceAction action. For all other actions,
+ this struct is undefined.
+ */
+ struct {
+ int32_t format;
+ int32_t width;
+ int32_t height;
+ } changed;
+ } data;
+ } surface;
int32_t other[8];
} data;
};