我有一些问题,我使用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;
}
答案 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;
}
使用这些功能,我们会在首次设置窗口时通过一个函数收到通知,并在每次更新时调用另一个函数。