/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Pierre Phaneuf * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /******************************************************************************* * npsimple.cpp ****************************************************************************** * Simple Sample Plugin * Copyright (c) 1996 Netscape Communications. All rights reserved. ****************************************************************************** * OVERVIEW * -------- * Section 1 - Includes * Section 2 - Instance Structs * Section 3 - API Plugin Implementations * Section 4 - Utility Method Implementations *******************************************************************************/ /******************************************************************************* * SECTION 1 - Includes ******************************************************************************/ #include #include #include "nsplugin.h" #include "nsIServiceManager.h" #include "nsISupports.h" #include "nsIFactory.h" #include "nsIGenericFactory.h" #include "nsMemory.h" #include "nsString.h" #include "simpleCID.h" #include "nsISimplePluginInstance.h" #include "nsIScriptablePlugin.h" /*------------------------------------------------------------------------------ * Windows Includes *----------------------------------------------------------------------------*/ #ifdef _WINDOWS /* Windows Includes */ #include #endif /* _WINDOWS */ /*------------------------------------------------------------------------------ * UNIX includes *----------------------------------------------------------------------------*/ #ifdef XP_UNIX #include #include #include #include #include #endif /* XP_UNIX */ #ifdef XP_UNIX gboolean draw (GtkWidget *widget, GdkEventExpose *event, gpointer data); #endif /******************************************************************************* * SECTION 2 - Instance Structs ******************************************************************************* * Instance state information about the plugin. * * PLUGIN DEVELOPERS: * Use this struct to hold per-instance information that you'll * need in the various functions in this file. ****************************************************************************** * First comes the PlatformInstance struct, which contains platform specific * information for each instance. *****************************************************************************/ /*------------------------------------------------------------------------------ * Windows PlatformInstance *----------------------------------------------------------------------------*/ #if defined(XP_WIN) // XXXX OS2TODO typedef struct _PlatformInstance { HWND fhWnd; WNDPROC fDefaultWindowProc; } PlatformInstance; /*------------------------------------------------------------------------------ * UNIX PlatformInstance *----------------------------------------------------------------------------*/ #elif defined(XP_UNIX) typedef struct _PlatformInstance { Window window; GtkWidget *moz_box; GdkSuperWin *superwin; GtkWidget *label; Display * display; uint32 x, y; uint32 width, height; } PlatformInstance; /*------------------------------------------------------------------------------ * Macintosh PlatformInstance *----------------------------------------------------------------------------*/ #elif defined(XP_MAC) typedef struct _PlatformInstance { int placeholder; } PlatformInstance; /*------------------------------------------------------------------------------ * Stub PlatformInstance *----------------------------------------------------------------------------*/ #else typedef struct _PlatformInstance { int placeholder; } PlatformInstance; #endif /* end Section 2 */ // Define constants for easy use static NS_DEFINE_CID(kSimplePluginCID, NS_SIMPLEPLUGIN_CID); static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID); #define PLUGIN_MIME_TYPE "application/x-simple" static const char kPluginName[] = "Simple Sample Plug-in"; static const char kPluginDescription[] = "Demonstrates a simple plug-in."; static const char* kMimeTypes[] = { PLUGIN_MIME_TYPE }; static const char* kMimeDescriptions[] = { "Simple Sample Plug-in" }; static const char* kFileExtensions[] = { "smp" }; static const PRInt32 kNumMimeTypes = sizeof(kMimeTypes) / sizeof(*kMimeTypes); //////////////////////////////////////////////////////////////////////////////// // Simple Plugin Classes //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // SimplePluginInstance represents an instance of the simple plugin class. class SimplePluginInstance : public nsIPluginInstance, public nsIScriptablePlugin, public nsISimplePluginInstance { public: //////////////////////////////////////////////////////////////////////////// // for implementing a generic module static NS_METHOD Create(nsISupports* aOuter, REFNSIID aIID, void** aResult); static NS_METHOD RegisterSelf(nsIComponentManager* aCompMgr, nsIFile* aPath, const char* aRegistryLocation, const char* aComponentType, const nsModuleComponentInfo *info); static NS_METHOD UnregisterSelf(nsIComponentManager* aCompMgr, nsIFile* aPath, const char* aRegistryLocation, const nsModuleComponentInfo *info); NS_DECL_ISUPPORTS NS_DECL_NSISCRIPTABLEPLUGIN NS_DECL_NSISIMPLEPLUGININSTANCE //////////////////////////////////////////////////////////////////////////// // from nsIEventHandler: // (Corresponds to NPP_HandleEvent.) // Note that for Unix and Mac the nsPluginEvent structure is different // from the old NPEvent structure -- it's no longer the native event // record, but is instead a struct. This was done for future extensibility, // and so that the Mac could receive the window argument too. For Windows // and OS2, it's always been a struct, so there's no change for them. NS_IMETHOD HandleEvent(nsPluginEvent* event, PRBool* handled); //////////////////////////////////////////////////////////////////////////// // from nsIPluginInstance: NS_IMETHOD Initialize(nsIPluginInstancePeer* peer); // Required backpointer to the peer. NS_IMETHOD GetPeer(nsIPluginInstancePeer* *result); // See comment for nsIPlugin::CreateInstance, above. NS_IMETHOD Start(void); // The old NPP_Destroy call has been factored into two plugin instance // methods: // // Stop -- called when the plugin instance is to be stopped (e.g. by // displaying another plugin manager window, causing the page containing // the plugin to become removed from the display). // // Destroy -- called once, before the plugin instance peer is to be // destroyed. This method is used to destroy the plugin instance. NS_IMETHOD Stop(void); NS_IMETHOD Destroy(void); // (Corresponds to NPP_SetWindow.) NS_IMETHOD SetWindow(nsPluginWindow* window); NS_IMETHOD NewStream(nsIPluginStreamListener** listener); // (Corresponds to NPP_Print.) NS_IMETHOD Print(nsPluginPrint* platformPrint); NS_IMETHOD GetValue(nsPluginInstanceVariable variable, void *value); //////////////////////////////////////////////////////////////////////////// // SimplePluginInstance specific methods: SimplePluginInstance(void); virtual ~SimplePluginInstance(void); void PlatformNew(void); nsresult PlatformDestroy(void); nsresult PlatformSetWindow(nsPluginWindow* window); PRInt16 PlatformHandleEvent(nsPluginEvent* event); void SetMode(nsPluginMode mode) { fMode = mode; } #ifdef XP_UNIX NS_IMETHOD Repaint(void); #endif #ifdef XP_WIN static LRESULT CALLBACK PluginWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); #endif char* fText; protected: nsIPluginInstancePeer* fPeer; nsPluginWindow* fWindow; nsPluginMode fMode; PlatformInstance fPlatform; }; //////////////////////////////////////////////////////////////////////////////// // SimplePluginStream represents the stream used by SimplePluginInstances // to receive data from the browser. class SimplePluginStreamListener : public nsIPluginStreamListener { public: NS_DECL_ISUPPORTS //////////////////////////////////////////////////////////////////////////// // from nsIPluginStreamListener: /** * Notify the observer that the URL has started to load. This method is * called only once, at the beginning of a URL load.

* * @return The return value is currently ignored. In the future it may be * used to cancel the URL load.. */ NS_IMETHOD OnStartBinding(nsIPluginStreamInfo* pluginInfo); /** * Notify the client that data is available in the input stream. This * method is called whenver data is written into the input stream by the * networking library...

* * @param aIStream The input stream containing the data. This stream can * be either a blocking or non-blocking stream. * @param length The amount of data that was just pushed into the stream. * @return The return value is currently ignored. */ NS_IMETHOD OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length); NS_IMETHOD OnFileAvailable(nsIPluginStreamInfo* pluginInfo, const char* fileName); /** * Notify the observer that the URL has finished loading. This method is * called once when the networking library has finished processing the * URL transaction initiatied via the nsINetService::Open(...) call.

* * This method is called regardless of whether the URL loaded successfully.

* * @param status Status code for the URL load. * @param msg A text string describing the error. * @return The return value is currently ignored. */ NS_IMETHOD OnStopBinding(nsIPluginStreamInfo* pluginInfo, nsresult status); NS_IMETHOD OnNotify(const char* url, nsresult status); NS_IMETHOD GetStreamType(nsPluginStreamType *result); //////////////////////////////////////////////////////////////////////////// // SimplePluginStreamListener specific methods: SimplePluginStreamListener(SimplePluginInstance* inst, const char* url); virtual ~SimplePluginStreamListener(void); protected: const char* fMessageName; }; /******************************************************************************* * SECTION 3 - API Plugin Implementations ******************************************************************************/ // XXXwaterson document! static const nsModuleComponentInfo gComponentInfo[] = { { "Simple Plugin", NS_SIMPLEPLUGIN_CID, NS_INLINE_PLUGIN_CONTRACTID_PREFIX PLUGIN_MIME_TYPE, SimplePluginInstance::Create, SimplePluginInstance::RegisterSelf, SimplePluginInstance::UnregisterSelf }, }; NS_IMPL_NSGETMODULE(SimplePlugin, gComponentInfo) //////////////////////////////////////////////////////////////////////////////// // nsIScriptablePlugin methods //////////////////////////////////////////////////////////////////////////////// NS_METHOD SimplePluginInstance::GetScriptablePeer(void **aScriptablePeer) { // We implement the interface we want to be scriptable by // (nsISimplePluginInstance) so we just return this. // NOTE if this function returns something other than // nsIPluginInstance, then that object will also need to implement // nsISecurityCheckedComponent to be scriptable. The security // system knows to special-case nsIPluginInstance when checking // security, but in general, XPCOM components must implement // nsISecurityCheckedComponent to be scriptable from content // javascript. *aScriptablePeer = NS_STATIC_CAST(nsISimplePluginInstance *, this); NS_ADDREF(NS_STATIC_CAST(nsISimplePluginInstance *, *aScriptablePeer)); return NS_OK; } NS_METHOD SimplePluginInstance::GetScriptableInterface(nsIID **aScriptableInterface) { *aScriptableInterface = (nsIID *)nsMemory::Alloc(sizeof(nsIID)); NS_ENSURE_TRUE(*aScriptableInterface, NS_ERROR_OUT_OF_MEMORY); **aScriptableInterface = NS_GET_IID(nsISimplePluginInstance); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // SimplePluginInstance Methods //////////////////////////////////////////////////////////////////////////////// NS_METHOD SimplePluginInstance::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult) { NS_PRECONDITION(aOuter == nsnull, "no aggregation"); if (aOuter) return NS_ERROR_NO_AGGREGATION; SimplePluginInstance* plugin = new SimplePluginInstance(); if (! plugin) return NS_ERROR_OUT_OF_MEMORY; nsresult rv; NS_ADDREF(plugin); rv = plugin->QueryInterface(aIID, aResult); NS_RELEASE(plugin); return rv; } NS_METHOD SimplePluginInstance::RegisterSelf(nsIComponentManager* aCompMgr, nsIFile* aPath, const char* aRegistryLocation, const char* aComponentType, const nsModuleComponentInfo *info) { nsresult rv; nsIServiceManager *svcMgr; rv = aCompMgr->QueryInterface(NS_GET_IID(nsIServiceManager), NS_REINTERPRET_CAST(void**, &svcMgr)); if (NS_FAILED(rv)) return rv; nsIPluginManager* pm; rv = svcMgr->GetService(kPluginManagerCID, NS_GET_IID(nsIPluginManager), NS_REINTERPRET_CAST(void**, &pm)); NS_RELEASE(svcMgr); if (NS_SUCCEEDED(rv)) { rv = pm->RegisterPlugin(kSimplePluginCID, kPluginName, kPluginDescription, kMimeTypes, kMimeDescriptions, kFileExtensions, kNumMimeTypes); NS_RELEASE(pm); } return rv; } NS_METHOD SimplePluginInstance::UnregisterSelf(nsIComponentManager* aCompMgr, nsIFile* aPath, const char* aRegistryLocation, const nsModuleComponentInfo *info) { nsresult rv; nsIServiceManager *svcMgr; rv = aCompMgr->QueryInterface(NS_GET_IID(nsIServiceManager), NS_REINTERPRET_CAST(void**, &svcMgr)); if (NS_FAILED(rv)) return rv; nsIPluginManager* pm; rv = svcMgr->GetService(kPluginManagerCID, NS_GET_IID(nsIPluginManager), NS_REINTERPRET_CAST(void**, &pm)); NS_RELEASE(svcMgr); if (NS_SUCCEEDED(rv)) { rv = pm->UnregisterPlugin(kSimplePluginCID); NS_RELEASE(pm); } return rv; } SimplePluginInstance::SimplePluginInstance(void) : fText(NULL), fPeer(NULL), fWindow(NULL), fMode(nsPluginMode_Embedded) { static const char text[] = "Hello World!"; fText = (char*) nsMemory::Clone(text, sizeof(text)); #ifdef XP_UNIX fPlatform.moz_box = nsnull; fPlatform.superwin = nsnull; fPlatform.label = nsnull; #endif } SimplePluginInstance::~SimplePluginInstance(void) { if(fText) nsMemory::Free(fText); PlatformDestroy(); // Perform platform specific cleanup } // These macros produce simple version of QueryInterface and AddRef. // See the nsISupports.h header file for details. NS_IMPL_ISUPPORTS3(SimplePluginInstance, nsIPluginInstance, nsISimplePluginInstance, nsIScriptablePlugin) /*+++++++++++++++++++++++++++++++++++++++++++++++++ * NewInstance: * Creates a new instance of a plug-in and returns an error value. * * NewInstance creates a new instance of your plug-in with MIME type specified * by pluginType. The parameter mode is NP_EMBED if the instance was created * by an EMBED tag, or NP_FULL if the instance was created by a separate file. * You can allocate any instance-specific private data in instance->pdata at this * time. The NPP pointer is valid until the instance is destroyed. +++++++++++++++++++++++++++++++++++++++++++++++++*/ NS_METHOD SimplePluginInstance::Initialize(nsIPluginInstancePeer* peer) { #ifdef NS_DEBUG printf("SimplePluginInstance::Initialize\n"); #endif NS_ASSERTION(peer != NULL, "null peer"); fPeer = peer; nsIPluginTagInfo* taginfo; const char* const* names = nsnull; const char* const* values = nsnull; PRUint16 count = 0; nsresult result; peer->AddRef(); result = peer->GetMode(&fMode); if (NS_FAILED(result)) return result; result = peer->QueryInterface(NS_GET_IID(nsIPluginTagInfo), (void **)&taginfo); if (NS_SUCCEEDED(result)) { taginfo->GetAttributes(count, names, values); NS_IF_RELEASE(taginfo); } #ifdef NS_DEBUG printf("Attribute count = %d\n", count); for (int i = 0; i < count; i++) { printf("plugin param=%s, value=%s\n", names[i], values[i]); } #endif PlatformNew(); /* Call Platform-specific initializations */ return NS_OK; } NS_METHOD SimplePluginInstance::GetPeer(nsIPluginInstancePeer* *result) { #ifdef NS_DEBUG printf("SimplePluginInstance::GetPeer\n"); #endif fPeer->AddRef(); *result = fPeer; return NS_OK; } NS_METHOD SimplePluginInstance::Start(void) { #ifdef NS_DEBUG printf("SimplePluginInstance::Start\n"); #endif return NS_OK; } NS_METHOD SimplePluginInstance::Stop(void) { #ifdef NS_DEBUG printf("SimplePluginInstance::Stop\n"); #endif return NS_OK; } NS_METHOD SimplePluginInstance::Destroy(void) { #ifdef NS_DEBUG printf("SimplePluginInstance::Destroy\n"); #endif return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * NPP_SetWindow: * Sets the window in which a plug-in draws, and returns an error value. * * NPP_SetWindow informs the plug-in instance specified by instance of the * the window denoted by window in which the instance draws. This nsPluginWindow * pointer is valid for the life of the instance, or until NPP_SetWindow is called * again with a different value. Subsequent calls to NPP_SetWindow for a given * instance typically indicate that the window has been resized. If either window * or window->window are NULL, the plug-in must not perform any additional * graphics operations on the window and should free any resources associated * with the window. +++++++++++++++++++++++++++++++++++++++++++++++++*/ NS_METHOD SimplePluginInstance::SetWindow(nsPluginWindow* window) { #ifdef NS_DEBUG printf("SimplePluginInstance::SetWindow\n"); #endif nsresult result; /* * PLUGIN DEVELOPERS: * Before setting window to point to the * new window, you may wish to compare the new window * info to the previous window (if any) to note window * size changes, etc. */ result = PlatformSetWindow(window); fWindow = window; return result; } NS_METHOD SimplePluginInstance::NewStream(nsIPluginStreamListener** listener) { #ifdef NS_DEBUG printf("SimplePluginInstance::NewStream\n"); #endif if(listener != NULL) { SimplePluginStreamListener* sl = new SimplePluginStreamListener(this, "http://www.mozilla.org"); if(!sl) return NS_ERROR_UNEXPECTED; sl->AddRef(); *listener = sl; } return NS_OK; } /* attribute string text; */ NS_IMETHODIMP SimplePluginInstance::GetText(char * *aText) { #ifdef NS_DEBUG printf("SimplePluginInstance::GetText\n"); #endif if(!fText) { *aText = NULL; return NS_OK; } char* ptr = *aText = (char*) nsMemory::Clone(fText, strlen(fText)+1); return ptr ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } NS_IMETHODIMP SimplePluginInstance::SetText(const char * aText) { #ifdef NS_DEBUG printf("SimplePluginInstance::SetText\n"); #endif if(fText) { nsMemory::Free(fText); fText = NULL; } if(aText) { fText = (char*) nsMemory::Clone(aText, strlen(aText)+1); if(!fText) return NS_ERROR_OUT_OF_MEMORY; #ifdef XP_WIN if(fPlatform.fhWnd) { InvalidateRect( fPlatform.fhWnd, NULL, TRUE ); UpdateWindow( fPlatform.fhWnd ); } #endif #ifdef XP_UNIX // force a redraw Repaint(); #endif } return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * NPP_Print: +++++++++++++++++++++++++++++++++++++++++++++++++*/ NS_METHOD SimplePluginInstance::Print(nsPluginPrint* printInfo) { #ifdef NS_DEBUG printf("SimplePluginInstance::Print\n"); #endif if (printInfo == NULL) return NS_ERROR_FAILURE; if (printInfo->mode == nsPluginMode_Full) { /* * PLUGIN DEVELOPERS: * If your plugin would like to take over * printing completely when it is in full-screen mode, * set printInfo->pluginPrinted to TRUE and print your * plugin as you see fit. If your plugin wants Netscape * to handle printing in this case, set * printInfo->pluginPrinted to FALSE (the default) and * do nothing. If you do want to handle printing * yourself, printOne is true if the print button * (as opposed to the print menu) was clicked. * On the Macintosh, platformPrint is a THPrint; on * Windows, platformPrint is a structure * (defined in npapi.h) containing the printer name, port, * etc. */ /* Do the default*/ printInfo->print.fullPrint.pluginPrinted = PR_FALSE; } else { /* If not fullscreen, we must be embedded */ /* * PLUGIN DEVELOPERS: * If your plugin is embedded, or is full-screen * but you returned false in pluginPrinted above, NPP_Print * will be called with mode == nsPluginMode_Embedded. The nsPluginWindow * in the printInfo gives the location and dimensions of * the embedded plugin on the printed page. On the * Macintosh, platformPrint is the printer port; on * Windows, platformPrint is the handle to the printing * device context. */ } return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * NPP_HandleEvent: * Mac-only, but stub must be present for Windows * Delivers a platform-specific event to the instance. * * On the Macintosh, event is a pointer to a standard Macintosh EventRecord. * All standard event types are passed to the instance as appropriate. In general, * return TRUE if you handle the event and FALSE if you ignore the event. +++++++++++++++++++++++++++++++++++++++++++++++++*/ NS_METHOD SimplePluginInstance::HandleEvent(nsPluginEvent* event, PRBool* handled) { #ifdef NS_DEBUG printf("SimplePluginInstance::HandleEvent\n"); #endif *handled = (PRBool)PlatformHandleEvent(event); return NS_OK; } NS_METHOD SimplePluginInstance::GetValue(nsPluginInstanceVariable variable, void *value) { #ifdef NS_DEBUG printf("SimplePluginInstance::GetValue\n"); #endif return NS_ERROR_FAILURE; } //////////////////////////////////////////////////////////////////////////////// // SimplePluginStreamListener Methods //////////////////////////////////////////////////////////////////////////////// SimplePluginStreamListener::SimplePluginStreamListener(SimplePluginInstance* inst, const char* msgName) : fMessageName(msgName) { char msg[256]; sprintf(msg, "### Creating SimplePluginStreamListener for %s\n", fMessageName); } SimplePluginStreamListener::~SimplePluginStreamListener(void) { char msg[256]; sprintf(msg, "### Destroying SimplePluginStreamListener for %s\n", fMessageName); } // This macro produces a simple version of QueryInterface, AddRef and Release. // See the nsISupports.h header file for details. NS_IMPL_ISUPPORTS1(SimplePluginStreamListener, nsIPluginStreamListener) NS_METHOD SimplePluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo) { #ifdef NS_DEBUG printf("SimplePluginStreamListener::OnStartBinding\n"); #endif char msg[256]; sprintf(msg, "### Opening plugin stream for %s\n", fMessageName); return NS_OK; } NS_METHOD SimplePluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo, nsIInputStream* input, PRUint32 length) { #ifdef NS_DEBUG printf("SimplePluginStreamListener::OnDataAvailable\n"); #endif char* buffer = new char[length]; if (buffer) { PRUint32 amountRead = 0; nsresult rslt = input->Read(buffer, length, &amountRead); if (rslt == NS_OK) { char msg[256]; sprintf(msg, "### Received %d bytes for %s\n", length, fMessageName); } delete buffer; } return NS_OK; } NS_METHOD SimplePluginStreamListener::OnFileAvailable(nsIPluginStreamInfo* pluginInfo, const char* fileName) { #ifdef NS_DEBUG printf("SimplePluginStreamListener::OnFileAvailable\n"); #endif char msg[256]; sprintf(msg, "### File available for %s: %s\n", fMessageName, fileName); return NS_OK; } NS_METHOD SimplePluginStreamListener::OnStopBinding(nsIPluginStreamInfo* pluginInfo, nsresult status ) { #ifdef NS_DEBUG printf("SimplePluginStreamListener::OnStopBinding\n"); #endif char msg[256]; sprintf(msg, "### Closing plugin stream for %s\n", fMessageName); return NS_OK; } NS_METHOD SimplePluginStreamListener::OnNotify(const char* url, nsresult status) { #ifdef NS_DEBUG printf("SimplePluginStreamListener::OnNotify\n"); #endif return NS_OK; } NS_METHOD SimplePluginStreamListener::GetStreamType(nsPluginStreamType *result) { #ifdef NS_DEBUG printf("SimplePluginStreamListener::GetStreamType\n"); #endif *result = nsPluginStreamType_Normal; return NS_OK; } /******************************************************************************* * SECTION 4 - Utility Method Implementations *******************************************************************************/ /*------------------------------------------------------------------------------ * Platform-Specific Implemenations *------------------------------------------------------------------------------ * UNIX Implementations *----------------------------------------------------------------------------*/ #if defined(XP_UNIX) /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformNew * * Initialize any Platform-Specific instance data. +++++++++++++++++++++++++++++++++++++++++++++++++*/ void SimplePluginInstance::PlatformNew(void) { fPlatform.window = 0; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformDestroy * * Destroy any Platform-Specific instance data. +++++++++++++++++++++++++++++++++++++++++++++++++*/ nsresult SimplePluginInstance::PlatformDestroy(void) { gtk_widget_destroy(fPlatform.moz_box); fPlatform.moz_box = 0; return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformSetWindow * * Perform platform-specific window operations +++++++++++++++++++++++++++++++++++++++++++++++++*/ nsresult SimplePluginInstance::PlatformSetWindow(nsPluginWindow* window) { #ifdef NS_DEBUG printf("SimplePluginInstance::PlatformSetWindow\n"); #endif if (window == NULL || window->window == NULL) return NS_ERROR_NULL_POINTER; GdkWindow *win = gdk_window_lookup((XID)window->window); if ( fPlatform.superwin && fPlatform.superwin->bin_window == win ) return NS_OK; // should we destroy fPlatform.superwin ?? fPlatform.superwin = gdk_superwin_new(win, 0, 0, window->width, window->height); // a little cleanup if (fPlatform.label) gtk_widget_destroy(fPlatform.label); if (fPlatform.moz_box) gtk_widget_destroy(fPlatform.moz_box); // create a containing mozbox and a label to put in it fPlatform.moz_box = gtk_mozbox_new(fPlatform.superwin->bin_window); fPlatform.label = gtk_label_new(fText); gtk_container_add(GTK_CONTAINER(fPlatform.moz_box), fPlatform.label); // grow the label to fit the entire mozbox gtk_widget_set_usize(fPlatform.label, window->width, window->height); // connect to expose events gtk_signal_connect (GTK_OBJECT(fPlatform.label), "expose_event", GTK_SIGNAL_FUNC(draw), this); gtk_widget_show(fPlatform.label); gtk_widget_show(fPlatform.moz_box); return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformHandleEvent * * Handle platform-specific events. +++++++++++++++++++++++++++++++++++++++++++++++++*/ int16 SimplePluginInstance::PlatformHandleEvent(nsPluginEvent* event) { /* UNIX Plugins do not use HandleEvent */ return 0; } NS_IMETHODIMP SimplePluginInstance::Repaint(void) { #ifdef DEBUG printf("SimplePluginInstance::Repaint()\n"); #endif if ( !fPlatform.moz_box || !fPlatform.label ) return NS_ERROR_FAILURE; // Set the label text gtk_label_set_text(GTK_LABEL(fPlatform.label), fText); // show the new label gtk_widget_show(fPlatform.label); gtk_widget_show(fPlatform.moz_box); return NS_OK; } gboolean draw (GtkWidget *widget, GdkEventExpose *event, gpointer data) { SimplePluginInstance * pthis = (SimplePluginInstance *)data; pthis->Repaint(); return TRUE; } /*------------------------------------------------------------------------------ * Windows Implementations *----------------------------------------------------------------------------*/ #elif defined(XP_WIN) const char* gInstanceLookupString = "instance->pdata"; /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformNew * * Initialize any Platform-Specific instance data. +++++++++++++++++++++++++++++++++++++++++++++++++*/ void SimplePluginInstance::PlatformNew(void) { fPlatform.fhWnd = NULL; fPlatform.fDefaultWindowProc = NULL; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformDestroy * * Destroy any Platform-Specific instance data. +++++++++++++++++++++++++++++++++++++++++++++++++*/ nsresult SimplePluginInstance::PlatformDestroy(void) { if( fWindow != NULL ) { /* If we have a window, clean * it up. */ SetWindowLong( fPlatform.fhWnd, GWL_WNDPROC, (LONG)fPlatform.fDefaultWindowProc); fPlatform.fDefaultWindowProc = NULL; fPlatform.fhWnd = NULL; } return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformSetWindow * * Perform platform-specific window operations +++++++++++++++++++++++++++++++++++++++++++++++++*/ nsresult SimplePluginInstance::PlatformSetWindow(nsPluginWindow* window) { if( fWindow != NULL ) /* If we already have a window, clean * it up before trying to subclass * the new window. */ { if( (window == NULL) || ( window->window == NULL ) ) { /* There is now no window to use. get rid of the old * one and exit. */ SetWindowLong( fPlatform.fhWnd, GWL_WNDPROC, (LONG)fPlatform.fDefaultWindowProc); fPlatform.fDefaultWindowProc = NULL; fPlatform.fhWnd = NULL; return NS_OK; } else if ( fPlatform.fhWnd == (HWND) window->window ) { /* The new window is the same as the old one. Exit now. */ return NS_OK; } else { /* Clean up the old window, so that we can subclass the new * one later. */ SetWindowLong( fPlatform.fhWnd, GWL_WNDPROC, (LONG)fPlatform.fDefaultWindowProc); fPlatform.fDefaultWindowProc = NULL; fPlatform.fhWnd = NULL; } } else if( (window == NULL) || ( window->window == NULL ) ) { /* We can just get out of here if there is no current * window and there is no new window to use. */ return NS_OK; } /* At this point, we will subclass * window->window so that we can begin drawing and * receiving window messages. */ fPlatform.fDefaultWindowProc = (WNDPROC)SetWindowLong( (HWND)window->window, GWL_WNDPROC, (LONG)SimplePluginInstance::PluginWindowProc); fPlatform.fhWnd = (HWND) window->window; SetProp(fPlatform.fhWnd, gInstanceLookupString, (HANDLE)this); InvalidateRect( fPlatform.fhWnd, NULL, TRUE ); UpdateWindow( fPlatform.fhWnd ); return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformHandleEvent * * Handle platform-specific events. +++++++++++++++++++++++++++++++++++++++++++++++++*/ PRInt16 SimplePluginInstance::PlatformHandleEvent(nsPluginEvent* event) { /* Windows Plugins use the Windows event call-back mechanism for events. (See PluginWindowProc) */ return 0; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PluginWindowProc * * Handle the Windows window-event loop. +++++++++++++++++++++++++++++++++++++++++++++++++*/ LRESULT CALLBACK SimplePluginInstance::PluginWindowProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { SimplePluginInstance* inst = (SimplePluginInstance*) GetProp(hWnd, gInstanceLookupString); switch( Msg ) { case WM_PAINT: { PAINTSTRUCT paintStruct; HDC hdc; hdc = BeginPaint( hWnd, &paintStruct ); if(paintStruct.fErase) FillRect(hdc, &paintStruct.rcPaint, (HBRUSH) GetStockObject(WHITE_BRUSH)); if(inst->fText) { RECT rcWnd; GetWindowRect(hWnd, &rcWnd); SetTextAlign(hdc, TA_CENTER); TextOut(hdc, (rcWnd.right-rcWnd.left)/2, (rcWnd.bottom-rcWnd.top)/2, inst->fText, strlen(inst->fText)); } EndPaint( hWnd, &paintStruct ); break; } default: { CallWindowProc(inst->fPlatform.fDefaultWindowProc, hWnd, Msg, wParam, lParam); } } return 0; } /*------------------------------------------------------------------------------ * Macintosh Implementations *----------------------------------------------------------------------------*/ #elif defined(XP_MAC) PRBool StartDraw(nsPluginWindow* window); void EndDraw(nsPluginWindow* window); void DoDraw(SimplePluginInstance* This); CGrafPort gSavePort; CGrafPtr gOldPort; /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformNew * * Initialize any Platform-Specific instance data. +++++++++++++++++++++++++++++++++++++++++++++++++*/ void SimplePluginInstance::PlatformNew(void) { } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformDestroy * * Destroy any Platform-Specific instance data. +++++++++++++++++++++++++++++++++++++++++++++++++*/ nsresult SimplePluginInstance::PlatformDestroy(void) { return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformSetWindow * * Perform platform-specific window operations +++++++++++++++++++++++++++++++++++++++++++++++++*/ nsresult SimplePluginInstance::PlatformSetWindow(nsPluginWindow* window) { fWindow = window; if( StartDraw( window ) ) { DoDraw(This); EndDraw( window ); } return NS_OK; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * PlatformHandleEvent * * Handle platform-specific events. +++++++++++++++++++++++++++++++++++++++++++++++++*/ int16 SimplePluginInstance::PlatformHandleEvent(nsPluginEvent* event) { int16 eventHandled = FALSE; EventRecord* ev = (EventRecord*) event; if (This != NULL && event != NULL) { switch (ev->what) { /* * Draw ourselves on update events */ case updateEvt: if( StartDraw( fWindow ) ) { DoDraw(This); EndDraw( fWindow ); } eventHandled = true; break; default: break; } } return eventHandled; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * StartDraw +++++++++++++++++++++++++++++++++++++++++++++++++*/ PRBool SimplePluginInstance::StartDraw(nsPluginWindow* window) { NP_Port* port; Rect clipRect; RGBColor col; if (window == NULL) return FALSE; port = (NP_Port*) window->window; if (window->clipRect.left < window->clipRect.right) { /* Preserve the old port */ GetPort((GrafPtr*)&gOldPort); SetPort((GrafPtr)port->port); /* Preserve the old drawing environment */ gSavePort.portRect = port->port->portRect; gSavePort.txFont = port->port->txFont; gSavePort.txFace = port->port->txFace; gSavePort.txMode = port->port->txMode; gSavePort.rgbFgColor = port->port->rgbFgColor; gSavePort.rgbBkColor = port->port->rgbBkColor; GetClip(gSavePort.clipRgn); /* Setup our drawing environment */ clipRect.top = window->clipRect.top + port->porty; clipRect.left = window->clipRect.left + port->portx; clipRect.bottom = window->clipRect.bottom + port->porty; clipRect.right = window->clipRect.right + port->portx; SetOrigin(port->portx,port->porty); ClipRect(&clipRect); clipRect.top = clipRect.left = 0; TextSize(12); TextFont(geneva); TextMode(srcCopy); col.red = col.green = col.blue = 0; RGBForeColor(&col); col.red = col.green = col.blue = 65000; RGBBackColor(&col); return TRUE; } else return FALSE; } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * EndDraw +++++++++++++++++++++++++++++++++++++++++++++++++*/ void SimplePluginInstance::EndDraw(nsPluginWindow* window) { CGrafPtr myPort; NP_Port* port = (NP_Port*) window->window; SetOrigin(gSavePort.portRect.left, gSavePort.portRect.top); SetClip(gSavePort.clipRgn); GetPort((GrafPtr*)&myPort); myPort->txFont = gSavePort.txFont; myPort->txFace = gSavePort.txFace; myPort->txMode = gSavePort.txMode; RGBForeColor(&gSavePort.rgbFgColor); RGBBackColor(&gSavePort.rgbBkColor); SetPort((GrafPtr)gOldPort); } /*+++++++++++++++++++++++++++++++++++++++++++++++++ * DoDraw +++++++++++++++++++++++++++++++++++++++++++++++++*/ void SimplePluginInstance::DoDraw(void) { Rect drawRect; drawRect.top = 0; drawRect.left = 0; drawRect.bottom = drawRect.top + fWindow->height; drawRect.right = drawRect.left + fWindow->width; EraseRect( &drawRect ); MoveTo( 2, 12 ); DrawString("\pHello, World!"); } /*------------------------------------------------------------------------------ * Stub Implementations *----------------------------------------------------------------------------*/ #else void SimplePluginInstance::PlatformNew(void) { } nsresult SimplePluginInstance::PlatformDestroy(void) { return NS_ERROR_NOT_IMPLEMENTED; } nsresult SimplePluginInstance::PlatformSetWindow(nsPluginWindow* window) { return NS_ERROR_NOT_IMPLEMENTED; } int16 SimplePluginInstance::PlatformHandleEvent(nsPluginEvent* event) { int16 eventHandled = FALSE; return eventHandled; } #endif /* end Section 5 */ /******************************************************************************/