【问题标题】:NPAPI plugin develop on mac10.8NPAPI插件在mac10.8上开发
【发布时间】:2012-11-08 13:31:12
【问题描述】:

我有一些问题,我用xcode在mac10.8上写了一个npapi插件,我想在插件上画图但是当我通过NPP_SetWindow(NPP instance, NPWindow* pNPWindow);得到pNPWindow->window指针时;我发现 nNPWindow->window 是 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;
    }

【问题讨论】:

    标签: macos plugins npapi


    【解决方案1】:

    您要在 Mac 10.8 上使用的任何东西都不支持 carbon 事件模型,因此 window 将始终为 NULL。假设您尝试使用 CoreGraphics 绘图模型,当触发事件进行绘图时,您将获得 CGContextRef。

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

    您可能想看看FireBreath,它适用于 10.8 并为您抽象了这些东西的所有复杂性。

    【讨论】:

    • 作为后续,如果您希望您的插件在现代浏览器中作为 32 位插件工作,您应该协商 Cocoa 事件模型和 CoreGraphics 绘图模型。我猜您正在使用 64 位进行测试,因为您看到了 Cocoa 事件模型行为(NULL 窗口指针),但在您发布的代码中没有 Cocoa 协商。 Cocoa 是 64 位的默认设置,但不是 32 位,如果您希望您的插件在 Chrome 中工作(或为以 32 位模式启动浏览器的人),您应该为这两者编译。
    【解决方案2】:

    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* 窗口”将取消对 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并子类化window,这样我们就可以得到自己的window event 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;
    }
    

    使用这些函数,我们会在第一次设置窗口时在一个函数中收到通知,而在每次进行更新时调用另一个函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-11
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多