void PluginWidgetAndroid::layoutSurface(bool pluginBoundsChanged) {

    if (m_drawingModel != kSurface_ANPDrawingModel)
        return;
    if (!m_pluginWindow)
        return;


    bool displayPlugin = m_pluginView->isVisible() && !m_isSurfaceClippedOut;
    PLUGIN_LOG("%p DisplayPlugin[%d] visible=[%d] clipped=[%d]",
            m_pluginView->instance(), displayPlugin,
            m_pluginView->isVisible(), m_isSurfaceClippedOut);

    // if the surface does not exist then create a new surface
    if (!m_embeddedView && displayPlugin) {

        WebCore::PluginPackage* pkg = m_pluginView->plugin();
        NPP instance = m_pluginView->instance();

        jobject pluginSurface;
        pkg->pluginFuncs()->getvalue(instance, kJavaSurface_ANPGetValue,
                                     static_cast<void*>(&pluginSurface));

        jobject tempObj = m_core->addSurface(pluginSurface,
                m_pluginWindow->x, m_pluginWindow->y,
                m_pluginWindow->width, m_pluginWindow->height);

        if (tempObj) {
            JNIEnv* env = JSC::Bindings::getJNIEnv();
            m_embeddedView = env->NewGlobalRef(tempObj);
            m_embeddedViewAttached = true;
        }
    // if the view is unattached but visible then attach it
    } else if (m_embeddedView && !m_embeddedViewAttached && displayPlugin && !m_isFullScreen) {
        m_core->updateSurface(m_embeddedView, m_pluginWindow->x, m_pluginWindow->y,
                              m_pluginWindow->width, m_pluginWindow->height);
        m_embeddedViewAttached = true;
    // if the view is attached but invisible then remove it
    } else if (m_embeddedView && m_embeddedViewAttached && !displayPlugin) {
        m_core->destroySurface(m_embeddedView);
        m_embeddedViewAttached = false;
    // if the plugin's bounds have changed and it's visible then update it
    } else if (pluginBoundsChanged && displayPlugin && !m_isFullScreen) {
        m_core->updateSurface(m_embeddedView, m_pluginWindow->x, m_pluginWindow->y,
                              m_pluginWindow->width, m_pluginWindow->height);

    }
}
void PluginWidgetAndroid::requestFullScreen() {
    if (m_isFullScreen) {
        return;
    }

    if (!m_embeddedView && m_drawingModel == kOpenGL_ANPDrawingModel) {
        WebCore::PluginPackage* pkg = m_pluginView->plugin();
        NPP instance = m_pluginView->instance();

        jobject pluginSurface;
        pkg->pluginFuncs()->getvalue(instance, kJavaSurface_ANPGetValue,
                                     static_cast<void*>(&pluginSurface));

        // create the surface, but do not add it to the view hierarchy
        jobject tempObj = m_core->createSurface(pluginSurface);

        if (tempObj) {
            JNIEnv* env = JSC::Bindings::getJNIEnv();
            m_embeddedView = env->NewGlobalRef(tempObj);
            m_embeddedViewAttached = false;
        }
    }

    if (!m_embeddedView) {
        return;
    }

    // send event to notify plugin of full screen change
    ANPEvent event;
    SkANP::InitEvent(&event, kLifecycle_ANPEventType);
    event.data.lifecycle.action = kEnterFullScreen_ANPLifecycleAction;
    sendEvent(event);

    // remove the embedded surface from the view hierarchy
    if (m_drawingModel != kOpenGL_ANPDrawingModel)
        m_core->destroySurface(m_embeddedView);

    // add the full screen view
    m_core->showFullScreenPlugin(m_embeddedView, m_fullScreenOrientation,
                                 m_pluginView->instance());
    m_isFullScreen = true;
}
int16_t PluginWidgetAndroid::sendEvent(const ANPEvent& evt) {
    if (!m_acceptEvents)
        return 0;
    WebCore::PluginPackage* pkg = m_pluginView->plugin();
    NPP instance = m_pluginView->instance();
    // "missing" plugins won't have these
    if (pkg && instance) {

        // if the plugin is gaining focus then update our state now to allow
        // the plugin's event handler to perform actions that require focus
        if (evt.eventType == kLifecycle_ANPEventType &&
                evt.data.lifecycle.action == kGainFocus_ANPLifecycleAction) {
            m_hasFocus = true;
        }

#if DEBUG_EVENTS
        SkMSec startTime = SkTime::GetMSecs();
#endif

        // make a localCopy since the actual plugin may not respect its constness,
        // and so we don't want our caller to have its param modified
        ANPEvent localCopy = evt;
        int16_t result = pkg->pluginFuncs()->event(instance, &localCopy);

#if DEBUG_EVENTS
        SkMSec endTime = SkTime::GetMSecs();
        PLUGIN_LOG_EVENT(instance, &evt, result, endTime - startTime);
#endif

        // if the plugin is losing focus then delay the update of our state
        // until after we notify the plugin and allow them to perform actions
        // that may require focus
        if (evt.eventType == kLifecycle_ANPEventType &&
                evt.data.lifecycle.action == kLoseFocus_ANPLifecycleAction) {
            m_hasFocus = false;
        }

        return result;
    }
    return 0;
}
void PluginWidgetAndroid::draw(SkCanvas* canvas) {
    if (NULL == m_flipPixelRef || !m_flipPixelRef->isDirty()) {
        return;
    }
    
    SkAutoFlipUpdate update(m_flipPixelRef);
    const SkBitmap& bitmap = update.bitmap();
    const SkRegion& dirty = update.dirty();

    ANPEvent    event;
    SkANP::InitEvent(&event, kDraw_ANPEventType);

    event.data.drawContext.model = m_drawingModel;
    SkANP::SetRect(&event.data.drawContext.clip, dirty.getBounds());
    
    switch (m_drawingModel) {
        case kBitmap_ANPDrawingModel: {
            WebCore::PluginPackage* pkg = m_pluginView->plugin();
            NPP instance = m_pluginView->instance();
            
            if (SkANP::SetBitmap(&event.data.drawContext.data.bitmap,
                                 bitmap) &&
                    pkg->pluginFuncs()->event(instance, &event)) {
            
                if (canvas) {
                    SkBitmap bm(bitmap);
                    bm.setPixelRef(m_flipPixelRef);
                    canvas->drawBitmap(bm, SkIntToScalar(m_x),
                                           SkIntToScalar(m_y), NULL);
                }
            }
            break;
        }
        default:
            break;
    }
}