Back to index

lightning-sunbird  0.9+nobinonly
plugin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 
00039 #include <X11/Xlib.h>
00040 #include <X11/Intrinsic.h>
00041 #include <X11/cursorfont.h>
00042 
00043 #include "plugin.h"
00044 #include "nsIServiceManager.h"
00045 #include "nsISupportsUtils.h" // some usefule macros are defined here
00046 
00047 #define MIME_TYPES_HANDLED  "application/scriptable-plugin"
00048 #define PLUGIN_NAME         "Scriptable Example Plugin for Mozilla"
00049 #define MIME_TYPES_DESCRIPTION  MIME_TYPES_HANDLED":scr:"PLUGIN_NAME
00050 #define PLUGIN_DESCRIPTION  PLUGIN_NAME " (Plug-ins SDK sample)"
00051 
00052 char* NPP_GetMIMEDescription(void)
00053 {
00054     return(MIME_TYPES_DESCRIPTION);
00055 }
00056 
00058 //
00059 // general initialization and shutdown
00060 //
00061 NPError NS_PluginInitialize()
00062 {
00063   return NPERR_NO_ERROR;
00064 }
00065 
00066 void NS_PluginShutdown()
00067 {
00068 }
00069 
00070 // get values per plugin
00071 NPError NS_PluginGetValue(NPPVariable aVariable, void *aValue)
00072 {
00073   NPError err = NPERR_NO_ERROR;
00074   switch (aVariable) {
00075     case NPPVpluginNameString:
00076       *((char **)aValue) = PLUGIN_NAME;
00077       break;
00078     case NPPVpluginDescriptionString:
00079       *((char **)aValue) = PLUGIN_DESCRIPTION;
00080       break;
00081     default:
00082       err = NPERR_INVALID_PARAM;
00083       break;
00084   }
00085   return err;
00086 }
00087 
00088 
00090 //
00091 // construction and destruction of our plugin instance object
00092 //
00093 nsPluginInstanceBase * NS_NewPluginInstance(nsPluginCreateData * aCreateDataStruct)
00094 {
00095   if(!aCreateDataStruct)
00096     return NULL;
00097 
00098   nsPluginInstance * plugin = new nsPluginInstance(aCreateDataStruct->instance);
00099   return plugin;
00100 }
00101 
00102 void NS_DestroyPluginInstance(nsPluginInstanceBase * aPlugin)
00103 {
00104   if(aPlugin)
00105     delete (nsPluginInstance *)aPlugin;
00106 }
00107 
00109 //
00110 // nsPluginInstance class implementation
00111 //
00112 nsPluginInstance::nsPluginInstance(NPP aInstance) : nsPluginInstanceBase(),
00113   mInstance(aInstance),
00114   mInitialized(FALSE),
00115   mWindow(0),
00116   mXtwidget(0),
00117   mFontInfo(0),
00118   mScriptablePeer(NULL)
00119 {
00120   mString[0] = '\0';
00121 }
00122 
00123 nsPluginInstance::~nsPluginInstance()
00124 {
00125   // mScriptablePeer may be also held by the browser 
00126   // so releasing it here does not guarantee that it is over
00127   // we should take precaution in case it will be called later
00128   // and zero its mPlugin member
00129   mScriptablePeer->SetInstance(NULL);
00130   NS_IF_RELEASE(mScriptablePeer);
00131 }
00132 
00133 static void
00134 xt_event_handler(Widget xtwidget, nsPluginInstance *plugin, XEvent *xevent, Boolean *b)
00135 {
00136   switch (xevent->type) {
00137     case Expose:
00138       // get rid of all other exposure events
00139       if (plugin) {
00140         //while(XCheckTypedWindowEvent(plugin->Display(), plugin->Window(), Expose, xevent));
00141         plugin->draw();
00142       }
00143       default:
00144         break;
00145   }
00146 }
00147 
00148 void nsPluginInstance::draw()
00149 {
00150   unsigned int h = mHeight/2;
00151   unsigned int w = 3 * mWidth/4;
00152   int x = (mWidth - w)/2; // center
00153   int y = h/2;
00154   XClearArea(mDisplay, mWindow, 0, 0, 0, 0, False);
00155   if (x >= 0 && y >= 0) {
00156     GC gc = XCreateGC(mDisplay, mWindow, 0, NULL);
00157     if (!gc)
00158       return;
00159     XDrawRectangle(mDisplay, mWindow, gc, x, y, w, h);
00160     if (mString[0]) {
00161   int l = strlen(mString);
00162   int fmba = mFontInfo->max_bounds.ascent;
00163   int fmbd = mFontInfo->max_bounds.descent;
00164   int fh = fmba + fmbd;
00165   y += fh;
00166   x += 32;
00167       XDrawString(mDisplay, mWindow, gc, x, y, mString, l);
00168     }
00169     XFreeGC(mDisplay, gc);
00170   }
00171 }
00172 
00173 NPBool nsPluginInstance::init(NPWindow* aWindow)
00174 {
00175   if(aWindow == NULL)
00176     return FALSE;
00177 
00178   if (SetWindow(aWindow))
00179     mInitialized = TRUE;
00180          
00181   return mInitialized;
00182 }
00183 
00184 NPError nsPluginInstance::SetWindow(NPWindow* aWindow)
00185 {
00186   if(aWindow == NULL)
00187     return FALSE;
00188 
00189   mX = aWindow->x;
00190   mY = aWindow->y;
00191   mWidth = aWindow->width;
00192   mHeight = aWindow->height;
00193   if (mWindow != (Window) aWindow->window) {
00194     mWindow = (Window) aWindow->window;
00195     NPSetWindowCallbackStruct *ws_info = (NPSetWindowCallbackStruct *)aWindow->ws_info;
00196   mDisplay = ws_info->display;
00197   mVisual = ws_info->visual;
00198   mDepth = ws_info->depth;
00199   mColormap = ws_info->colormap;
00200 
00201   if (!mFontInfo) {
00202       if (!(mFontInfo = XLoadQueryFont(mDisplay, "9x15")))
00203     printf("Cannot open 9X15 font\n");
00204   }
00205   // add xt event handler
00206   Widget xtwidget = XtWindowToWidget(mDisplay, mWindow);
00207     if (xtwidget && mXtwidget != xtwidget) {
00208       mXtwidget = xtwidget;
00209     long event_mask = ExposureMask;
00210     XSelectInput(mDisplay, mWindow, event_mask);
00211     XtAddEventHandler(xtwidget, event_mask, False, (XtEventHandler)xt_event_handler, this);
00212   }
00213   }
00214   draw();
00215   return TRUE;
00216 }
00217 
00218 
00219 void nsPluginInstance::shut()
00220 {
00221   mInitialized = FALSE;
00222 }
00223 
00224 NPBool nsPluginInstance::isInitialized()
00225 {
00226   return mInitialized;
00227 }
00228 
00229 // this will force to draw a version string in the plugin window
00230 void nsPluginInstance::showVersion()
00231 {
00232   const char *ua = NPN_UserAgent(mInstance);
00233   strcpy(mString, ua);
00234   draw();
00235 }
00236 
00237 // this will clean the plugin window
00238 void nsPluginInstance::clear()
00239 {
00240   strcpy(mString, "");
00241   draw();
00242 }
00243 
00244 // ==============================
00245 // ! Scriptability related code !
00246 // ==============================
00247 //
00248 // here the plugin is asked by Mozilla to tell if it is scriptable
00249 // we should return a valid interface id and a pointer to 
00250 // nsScriptablePeer interface which we should have implemented
00251 // and which should be defined in the corressponding *.xpt file
00252 // in the bin/components folder
00253 NPError       nsPluginInstance::GetValue(NPPVariable aVariable, void *aValue)
00254 {
00255   NPError rv = NPERR_NO_ERROR;
00256 
00257   if (aVariable == NPPVpluginScriptableInstance) {
00258       // addref happens in getter, so we don't addref here
00259     nsIScriptablePluginSample * scriptablePeer = getScriptablePeer();
00260       if (scriptablePeer) {
00261         *(nsISupports **)aValue = scriptablePeer;
00262       } else
00263         rv = NPERR_OUT_OF_MEMORY_ERROR;
00264     }
00265   else if (aVariable == NPPVpluginScriptableIID) {
00266     static nsIID scriptableIID =  NS_ISCRIPTABLEPLUGINSAMPLE_IID;
00267       nsIID* ptr = (nsIID *)NPN_MemAlloc(sizeof(nsIID));
00268       if (ptr) {
00269           *ptr = scriptableIID;
00270           *(nsIID **)aValue = ptr;
00271       } else
00272         rv = NPERR_OUT_OF_MEMORY_ERROR;
00273   }
00274 
00275   return rv;
00276 }
00277 
00278 // ==============================
00279 // ! Scriptability related code !
00280 // ==============================
00281 //
00282 // this method will return the scriptable object (and create it if necessary)
00283 nsScriptablePeer* nsPluginInstance::getScriptablePeer()
00284 {
00285   if (!mScriptablePeer) {
00286     mScriptablePeer = new nsScriptablePeer(this);
00287     if(!mScriptablePeer)
00288       return NULL;
00289 
00290     NS_ADDREF(mScriptablePeer);
00291   }
00292 
00293   // add reference for the caller requesting the object
00294   NS_ADDREF(mScriptablePeer);
00295   return mScriptablePeer;
00296 }