1
votes

I have some problems,i use xcode write a npapi plugin on mac10.8,I want to draw a picture on the plugin but when i get the pNPWindow->window pointer through NPP_SetWindow(NPP instance, NPWindow* pNPWindow); I find that nNPWindow->window is NULL ,i spend must to find the problem,but i can not,somebody can help me。 sorry,my english so poor。

code is like that,

    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

2 Answers

2
votes

Anything you're going to use on Mac 10.8 won't support the carbon event model, so window will always be NULL. Assuming that you're trying to use the CoreGraphics drawing model you will get the CGContextRef when the event is fired to draw.

See https://wiki.mozilla.org/NPAPI:CocoaEventModel for more information on the Cocoa event model. The other option you have is the CoreAnimation model (with the InvalidatingCoreAnimation model on firefox and chrome)

You might want to take a look at FireBreath, which works on 10.8 and abstracts all of the complication of this stuff for you.

0
votes

NPP_SetWindow (NPP npp, NPWindow* pNPWindow)

For many, this will be where the real fun starts — this function is called to tell the plugin which window they are in. From the 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;   

A pointer to this structure is passed in with each call. On windows, the “void* window” will dereference to an HWND. On other platforms, it will likewise be dereferenced as an appropriate type.

Notice that again NPP npp is the first parameter. This will be the case on all NPP functions except NPP_New, where the mimetype is also passed in. Since we created a PluginInstance object and assigned it to npp->pdata in NPP_New, we need to create a small stub function to forward our NPP_New to a method on that object, like so:

// Called by browser whenever the window is changed, including to set up or destroy

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);
}

On windows, when SetWindow is called we need to save the HWND and subclass the window so that we can get our own 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;
}

With these functions, we get notified in one function when the window is first set, and another is called each time an update is made.