NPAPI插件在mac10.8上开发

时间:2012-11-08 13:31:13

标签: macos plugins npapi

我有一些问题,我使用xcode在mac10.8上写一个npapi插件,我想在插件上画一幅画,但是当我通过NPP_SetWindow得到pNPWindow->窗口指针时(NPP实例,NPWindow * pNPWindow) ;我发现nNPWindow->窗口是NULL,我花了必须找到问题,但我不能,有人可以帮助我。对不起,我的英语很差。

代码就是这样,

    NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*     argn[], char* argv[], NPSavedData* saved)
    {
        if(instance == NULL)
            return NPERR_INVALID_INSTANCE_ERROR;

        CPlugin *plugin = new CPlugin(instance);
        if(plugin == NULL)
            return NPERR_OUT_OF_MEMORY_ERROR;
        instance->pdata = (void *)plugin;

        NPBool supportsCG = false;
        NPError err;
        err = browser->getvalue(instance, NPNVsupportsCoreGraphicsBool,&supportsCG);

        if (err == NPERR_NO_ERROR && supportsCG)
             browser->setvalue(instance,NPPVpluginDrawingModel,(void*)NPDrawingModelCoreGraphics);

        return NPERR_NO_ERROR;
    }

    NPError NPP_SetWindow(NPP instance, NPWindow* pNPWindow)
   { 
        if(instance == NULL)
            return NPERR_INVALID_INSTANCE_ERROR;
        if(pNPWindow == NULL)
            return NPERR_GENERIC_ERROR;

        if(pNPWindow->window)
            writelog("window != NULL");

        if(pNPWindow->window == NULL)  //this is he problem pNPWindow->window always NULL
            writelog("window == NULL");

        return NPERR_NO_ERROR;
    }

2 个答案:

答案 0 :(得分:2)

您将在Mac 10.8上使用的任何内容都不支持碳事件模型,因此窗口将始终为NULL。假设您正在尝试使用CoreGraphics绘图模型,那么在触发事件时将获得CGContextRef。

有关Cocoa事件模型的更多信息,请参阅https://wiki.mozilla.org/NPAPI:CocoaEventModel。您拥有的另一个选项是CoreAnimation模型(在Firefox和Chrome上使用InvalidatingCoreAnimation模型)

您可能需要查看FireBreath,它适用于10.8,并为您提取所有这些内容的复杂功能。

答案 1 :(得分:0)

NPP_SetWindow(NPP npp,NPWindow * pNPWindow)

对于很多人来说,这将是真正有趣的开始 - 这个函数被调用来告诉插件他们在哪个窗口。来自Gecko SDK(npapi.h):

typedef struct _NPWindow
{
  void* window;  /* Platform specific window handle */
             /* OS/2: x - Position of bottom left corner  */
             /* OS/2: y - relative to visible netscape window */
  int32 x;       /* Position of top left corner relative */
  int32 y;       /* to a netscape page.                 */
  uint32 width;  /* Maximum window size */
  uint32 height;
  NPRect clipRect; /* Clipping rectangle in port coordinates */
               /* Used by MAC only.           */
  void * ws_info; /* Platform-dependent additonal data, linux specific */
  NPWindowType type; /* Is this a window or a drawable? */
} NPWindow;   

每次调用都会传入指向此结构的指针。在Windows上,“void * window”将取消引用HWND。在其他平台上,它同样会被解除引用为适当的类型。

请注意,NPP npp是第一个参数。除了NPP_New之外,所有NPP函数都是这种情况,其中mimetype也被传入。由于我们创建了一个PluginInstance对象并将其分配给NPP_New中的npp-> pdata,我们需要创建一个小的存根函数来转发我们的NPP_New对于该对象的方法,如下:

//每当窗口更改时由浏览器调用,包括设置或销毁

NPErrorNPP_SetWindow (NPP npp, NPWindow* pNPWindow)
{
    if (npp == NULL)
         return NPERR_INVALID_INSTANCE_ERROR;
    else if (npp->pdata == NULL)
        return NPERR_GENERIC_ERROR;

    PluginInstance *inst = (PluginInstance *)npp->pdata;
    return inst->NpapiSetWindow(pNPWindow);
}

在Windows上,当调用SetWindow时,我们需要保存HWND并将窗口子类化,以便我们可以获得自己的窗口事件proc。

NPError PluginInstance :: NpapiSetWindow(NPWindow * pNPWindow) {     NPError rv = NPERR_NO_ERROR;

if(pNPWindow == NULL)
    return NPERR_GENERIC_ERROR;

// window just created; in initWindow, set initialized to true
if(!this->initialized) {
    if(!this->initWindow(pNPWindow)) {
        return NPERR_MODULE_LOAD_FAILED_ERROR;
    }
}

// Window was already created; just pass on the updates
this->updateWindow(pNPWindow);

return rv;
}

使用这些功能,我们会在首次设置窗口时通过一个函数收到通知,并在每次更新时调用另一个函数。