/* -*- 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): * Neil Hodgson * Mark Hammond * * 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 ***** */ // npevents.cxx // Demonstration plugin for Mozilla that handles events, focus and keystrokes. // See README.txt for more details. #include "nsplugin.h" #include "nsIServiceManager.h" #include "nsISupports.h" #include "nsIFactory.h" #include "nsIGenericFactory.h" #include "nsString.h" #include "nsIAllocator.h" #include "nsIEventsPluginInstance.h" #include #include #if defined (XP_WIN) #include #elif defined (XP_UNIX) #include #include #include #include #endif #define EVENTSPLUGIN_DEBUG /** * {CB2EF72A-856A-4818-8E72-3439395E335F} */ #define NS_EVENTSAMPLEPLUGIN_CID { 0xcb2ef72a, 0x856a, 0x4818, { 0x8e, 0x72, 0x34, 0x39, 0x39, 0x5e, 0x33, 0x5f } } #if defined(XP_UNIX) typedef struct _PlatformInstance { GtkWidget *moz_box; Display * display; uint32 x, y; uint32 width, height; } PlatformInstance; typedef GtkWidget* WinID; #endif // XP_UNIX #if defined(XP_WIN) typedef struct _PlatformInstance { WNDPROC fOldChildWindowProc; // The original WNDPROC of the edit control. WNDPROC fParentWindowProc; // The Mozilla WNDPROC for main (parent) window. } PlatformInstance; // Unique string for associating a pointer with our WNDPROC static const char* gInstanceLookupString = "instance->pdata"; typedef HWND WinID; #endif // XP_WIN static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID); static NS_DEFINE_CID(kEventsPluginCID, NS_EVENTSAMPLEPLUGIN_CID); const char *kPluginName = "Events Sample Plug-in"; const char *kPluginDescription = "Sample plugin that demonstrates events, focus and keystrokes."; #define PLUGIN_MIME_TYPE "application/x-events-sample-plugin" static const char* kMimeTypes[] = { PLUGIN_MIME_TYPE }; static const char* kMimeDescriptions[] = { "Event Sample Plug-in" }; static const char* kFileExtensions[] = { "smpev" }; static const PRInt32 kNumMimeTypes = sizeof(kMimeTypes) / sizeof(*kMimeTypes); //////////////////////////////////////////////////////////////////////////////// // EventsPluginInstance represents an instance of the EventsPlugin class. class EventsPluginInstance : public nsIPluginInstance, public nsIEventsSampleInstance { 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_NSIEVENTSSAMPLEINSTANCE //////////////////////////////////////////////////////////////////////////// // from nsIEventHandler: NS_IMETHOD HandleEvent(nsPluginEvent* event, PRBool* handled); //////////////////////////////////////////////////////////////////////////// // from nsIPluginInstance: NS_IMETHOD Initialize(nsIPluginInstancePeer *peer); // Required backpointer to the peer. NS_IMETHOD GetPeer(nsIPluginInstancePeer **result); NS_IMETHOD Start(void); NS_IMETHOD Stop(void); NS_IMETHOD Destroy(void); NS_IMETHOD SetWindow(nsPluginWindow* window); NS_IMETHOD NewStream(nsIPluginStreamListener** listener); NS_IMETHOD Print(nsPluginPrint* platformPrint); NS_IMETHOD GetValue(nsPluginInstanceVariable variable, void *value); //////////////////////////////////////////////////////////////////////////// // EventsPluginInstance specific methods: EventsPluginInstance(); virtual ~EventsPluginInstance(); void PlatformNew(void); nsresult PlatformDestroy(void); void PlatformResetWindow(); PRInt16 PlatformHandleEvent(nsPluginEvent* event); void PlatformResizeWindow(nsPluginWindow* window); nsresult PlatformCreateWindow(nsPluginWindow* window); void SetMode(nsPluginMode mode) { fMode = mode; } protected: //////////////////////////////////////////////////////////////////////////// // Implementation methods nsresult DoSetWindow(nsPluginWindow* window); // Data nsCOMPtr fPeer; nsPluginWindow *fWindow; // no nsCOMPtr as not an interface! nsPluginMode fMode; PlatformInstance fPlatform; WinID wMain; // The window created by Mozilla for us. WinID wChild; // The window we create as a child of the nsWindow. //////////////////////////////////////////////////////////////////////////// // Platform specific helpers #ifdef XP_WIN static LRESULT CALLBACK WndProcChild(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); #endif }; //////////////////////////////////////////////////////////////////////////////// // EventsPluginStream represents the stream used by EvMozs // to receive data from the browser. class EventsPluginStreamListener : 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. 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. 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. NS_IMETHOD OnStopBinding(nsIPluginStreamInfo* pluginInfo, nsresult status); NS_IMETHOD OnNotify(const char* url, nsresult status); NS_IMETHOD GetStreamType(nsPluginStreamType *result); //////////////////////////////////////////////////////////////////////////// // EventsPluginStreamListener specific methods: EventsPluginStreamListener(EventsPluginInstance *inst_, const char* url); virtual ~EventsPluginStreamListener(void); protected: const char* fMessageName; EventsPluginInstance *inst; }; // The module loader information. static const nsModuleComponentInfo gComponentInfo[] = { { "Events Sample Plugin", NS_EVENTSAMPLEPLUGIN_CID, NS_INLINE_PLUGIN_CONTRACTID_PREFIX PLUGIN_MIME_TYPE, EventsPluginInstance::Create, EventsPluginInstance::RegisterSelf, EventsPluginInstance::UnregisterSelf }, }; NS_IMPL_NSGETMODULE(EventsPlugin, gComponentInfo) //////////////////////////////////////////////////////////////////////////////// // EventsPluginInstance static Methods //////////////////////////////////////////////////////////////////////////////// NS_METHOD EventsPluginInstance::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult) { NS_PRECONDITION(aOuter == nsnull, "no aggregation"); if (aOuter) return NS_ERROR_NO_AGGREGATION; EventsPluginInstance* plugin = new EventsPluginInstance(); 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 EventsPluginInstance::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(kEventsPluginCID, kPluginName, kPluginDescription, kMimeTypes, kMimeDescriptions, kFileExtensions, kNumMimeTypes); NS_RELEASE(pm); } return rv; } NS_METHOD EventsPluginInstance::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(kEventsPluginCID); NS_RELEASE(pm); } return rv; } //////////////////////////////////////////////////////////////////////////////// // EventsPluginInstance Methods //////////////////////////////////////////////////////////////////////////////// // These macros produce simple version of QueryInterface and AddRef. // See the nsISupports.h header file for details. NS_IMPL_ISUPPORTS2(EventsPluginInstance, nsIPluginInstance, nsIEventsSampleInstance) EventsPluginInstance::EventsPluginInstance() : fPeer(NULL), fWindow(NULL), fMode(nsPluginMode_Embedded) { wChild = 0; } EventsPluginInstance::~EventsPluginInstance(void) { } NS_METHOD EventsPluginInstance::Initialize(nsIPluginInstancePeer *peer) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::Initialize\n"); #endif NS_ASSERTION(peer != NULL, "null peer"); fPeer = peer; nsCOMPtr 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; taginfo = do_QueryInterface(peer, &result); if (NS_SUCCEEDED(result)) { taginfo->GetAttributes(count, names, values); } PlatformNew(); /* Call Platform-specific initializations */ return NS_OK; } NS_METHOD EventsPluginInstance::GetPeer(nsIPluginInstancePeer* *result) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::GetPeer\n"); #endif *result = fPeer; NS_IF_ADDREF(*result); return NS_OK; } NS_METHOD EventsPluginInstance::Start(void) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::Start\n"); #endif return NS_OK; } NS_METHOD EventsPluginInstance::Stop(void) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::Stop\n"); #endif return NS_OK; } NS_METHOD EventsPluginInstance::Destroy(void) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::Destroy\n"); #endif PlatformDestroy(); // Perform platform specific cleanup 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 EventsPluginInstance::SetWindow(nsPluginWindow* window) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::SetWindow\n"); #endif nsresult result; result = DoSetWindow(window); fWindow = window; return result; } nsresult EventsPluginInstance::DoSetWindow(nsPluginWindow* window) { /* * 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. */ nsresult result = NS_OK; if ( fWindow != NULL ) { // If we already have a window, clean it up // before working with the new window if ( window && window->window && wMain == (WinID)window->window ) { /* The new window is the same as the old one. Exit now. */ PlatformResizeWindow(window); return NS_OK; } // Otherwise, just reset the window ready for the new one. PlatformResetWindow(); } 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; } if (window && window->window) { // Remember our main parent window. wMain = (WinID)window->window; // And create the child window. result = PlatformCreateWindow(window); } return result; } NS_METHOD EventsPluginInstance::NewStream(nsIPluginStreamListener** listener) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::NewStream\n"); #endif if (listener != NULL) { EventsPluginStreamListener* sl = new EventsPluginStreamListener(this, "http://www.mozilla.org"); if (!sl) return NS_ERROR_UNEXPECTED; sl->AddRef(); *listener = sl; } return NS_OK; } NS_METHOD EventsPluginInstance::Print(nsPluginPrint* printInfo) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::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 EventsPluginInstance::HandleEvent(nsPluginEvent* event, PRBool* handled) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::HandleEvent\n"); #endif *handled = (PRBool)PlatformHandleEvent(event); return NS_OK; } NS_METHOD EventsPluginInstance::GetValue(nsPluginInstanceVariable /*variable*/, void * /*value*/) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::GetValue\n"); #endif return NS_ERROR_FAILURE; } //////////////////////////////////////////////////////////////////////////////// // EventsPluginStreamListener Methods //////////////////////////////////////////////////////////////////////////////// EventsPluginStreamListener::EventsPluginStreamListener(EventsPluginInstance* inst_, const char* msgName) : fMessageName(msgName), inst(inst_) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginStreamListener: EventsPluginStreamListener for %s\n", fMessageName); #endif } EventsPluginStreamListener::~EventsPluginStreamListener(void) { } // This macro produces a simple version of QueryInterface, AddRef and Release. // See the nsISupports.h header file for details. NS_IMPL_ISUPPORTS1(EventsPluginStreamListener, nsIPluginStreamListener) NS_METHOD EventsPluginStreamListener::OnStartBinding(nsIPluginStreamInfo * /*pluginInfo*/) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginStreamListener::OnStartBinding\n"); printf("EventsPluginStreamListener: Opening plugin stream for %s\n", fMessageName); #endif return NS_OK; } NS_METHOD EventsPluginStreamListener::OnDataAvailable( nsIPluginStreamInfo * /*pluginInfo*/, nsIInputStream* input, PRUint32 length) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginStreamListener::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 EventsPluginStreamListener::OnFileAvailable( nsIPluginStreamInfo * /*pluginInfo*/, const char* fileName) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginStreamListener::OnFileAvailable\n"); #endif char msg[256]; sprintf(msg, "### File available for %s: %s\n", fMessageName, fileName); return NS_OK; } NS_METHOD EventsPluginStreamListener::OnStopBinding( nsIPluginStreamInfo * /*pluginInfo*/, nsresult /*status*/) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginStreamListener::OnStopBinding\n"); #endif char msg[256]; sprintf(msg, "### Closing plugin stream for %s\n", fMessageName); return NS_OK; } NS_METHOD EventsPluginStreamListener::OnNotify(const char * /*url*/, nsresult /*status*/) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginStreamListener::OnNotify\n"); #endif return NS_OK; } NS_METHOD EventsPluginStreamListener::GetStreamType(nsPluginStreamType *result) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginStreamListener::GetStreamType\n"); #endif *result = nsPluginStreamType_Normal; return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // Platform-Specific Implemenations // UNIX Implementations #ifdef XP_UNIX void EventsPluginInstance::PlatformNew(void) { fPlatform.moz_box = 0; } nsresult EventsPluginInstance::PlatformDestroy(void) { // the mozbox will be destroyed by the native destruction of the // widget's parent. return NS_OK; } void EventsPluginInstance::PlatformResetWindow() { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::PlatformResetWindow\n"); #endif fPlatform.moz_box = 0; } nsresult EventsPluginInstance::PlatformCreateWindow(nsPluginWindow* window) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::PlatformCreateWindow %lx\n", (long)window); #endif Window x_window = (Window)window->window; GdkWindow *gdk_window = (GdkWindow *)gdk_xid_table_lookup(x_window); if (!gdk_window) { fprintf(stderr, "NO WINDOW!!!\n"); return NS_ERROR_FAILURE; } fPlatform.moz_box = gtk_mozbox_new(gdk_window); wChild = gtk_entry_new(); gtk_container_add(GTK_CONTAINER(fPlatform.moz_box), wChild); gtk_widget_show_all(fPlatform.moz_box); return NS_OK; } void EventsPluginInstance::PlatformResizeWindow(nsPluginWindow* window) { NS_PRECONDITION(wChild, "Have no wChild!"); #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::PlatformResizeWindow to size (%d,%d)\n", window->width, window->height); #endif // Mozilla has already sized the mozbox - we just need to handle the child. gtk_widget_set_usize(wChild, window->width, window->height); } int16 EventsPluginInstance::PlatformHandleEvent(nsPluginEvent * /*event*/) { /* UNIX Plugins do not use HandleEvent */ return 0; } /* attribute string text; */ NS_IMETHODIMP EventsPluginInstance::GetVal(char * *aText) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::GetVal\n"); #endif char *text = gtk_entry_get_text(GTK_ENTRY(wChild)); *aText = reinterpret_cast(nsAllocator::Clone(text, strlen(text) + 1)); return (*aText) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } NS_IMETHODIMP EventsPluginInstance::SetVal(const char * aText) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::SetVal\n"); #endif gtk_entry_set_text(GTK_ENTRY(wChild), aText); return NS_OK; } #endif /* XP_UNIX */ // Windows Implementations #if defined(XP_WIN) void EventsPluginInstance::PlatformNew(void) { // Nothing to do! } nsresult EventsPluginInstance::PlatformDestroy(void) { wChild = 0; return NS_OK; } nsresult EventsPluginInstance::PlatformCreateWindow(nsPluginWindow* window) { // Remember parent wndproc. fPlatform.fParentWindowProc = (WNDPROC)::GetWindowLong(wMain, GWL_WNDPROC); NS_ABORT_IF_FALSE(fPlatform.fParentWindowProc!=NULL, "Couldn't get the parent WNDPROC"); // Create the child window that fills our nsWindow RECT rc; ::GetWindowRect(wMain, &rc); wChild = ::CreateWindow("Edit", // class - standard Windows edit control. "", // title WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL, // style 0, 0, rc.right-rc.left, rc.bottom-rc.top, wMain, // parent (HMENU)1111, // window ID 0, // instance NULL); //creation data. NS_ABORT_IF_FALSE(wChild != NULL, "Failed to create the child window!"); if (!wChild) return NS_ERROR_FAILURE; // Stash away our "this" pointer so our WNDPROC can talk to us. ::SetProp(wChild, gInstanceLookupString, (HANDLE)this); fPlatform.fOldChildWindowProc = (WNDPROC)::SetWindowLong( wChild, GWL_WNDPROC, (LONG)EventsPluginInstance::WndProcChild); return NS_OK; } int16 EventsPluginInstance::PlatformHandleEvent(nsPluginEvent * /*event*/) { return NS_OK; } void EventsPluginInstance::PlatformResetWindow() { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::PlatformResetWindow\n"); #endif fPlatform.fParentWindowProc = NULL; ::SetWindowLong(wChild, GWL_WNDPROC, (LONG)fPlatform.fOldChildWindowProc); fPlatform.fOldChildWindowProc = NULL; wChild = NULL; wMain = NULL; } void EventsPluginInstance::PlatformResizeWindow(nsPluginWindow* window) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::PlatformResizeWindow with new size (%d,%d)\n", window->width, window->height); #endif RECT rc; NS_PRECONDITION(wMain != nsnull, "Must have a valid wMain to resize"); ::GetClientRect(wMain, &rc); ::SetWindowPos(wChild, 0, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE); } /* attribute string text; */ NS_IMETHODIMP EventsPluginInstance::GetVal(char * *aText) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::GetVal\n"); #endif static char *empty = ""; char *value = empty; char buffer[256]; if (wChild) { GetWindowText(wChild, buffer, sizeof(buffer)/sizeof(buffer[0])); value = buffer; } *aText = reinterpret_cast(nsAllocator::Clone(value, strlen(value) + 1)); return (*aText) ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } NS_IMETHODIMP EventsPluginInstance::SetVal(const char * aText) { #ifdef EVENTSPLUGIN_DEBUG printf("EventsPluginInstance::SetVal\n"); #endif NS_ABORT_IF_FALSE(wChild != 0, "Don't have a window!"); SetWindowText(wChild, aText); return NS_OK; } // This is the WndProc for our child window (the edit control) LRESULT CALLBACK EventsPluginInstance::WndProcChild(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { EventsPluginInstance* inst = (EventsPluginInstance*) GetProp(hWnd, gInstanceLookupString); NS_ABORT_IF_FALSE(inst, "Could not get the inst from the Window!!"); switch (Msg) { // NOTE: We DONT pass on DBLCLK messages, as both Scintilla and // Mozilla have their own special logic, and they step on each other. // (causing our child to see a double-click as a triple-click) case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: case WM_SYSKEYUP: case WM_CHAR: case WM_SYSCHAR: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MOUSEMOVE: // pretend the message happened in our parent. return ::CallWindowProc(inst->fPlatform.fParentWindowProc, (HWND)inst->wMain, Msg, wParam, lParam); default: // let our child's default handle it. return ::CallWindowProc(inst->fPlatform.fOldChildWindowProc, hWnd, Msg, wParam, lParam); } /* not reached */ NS_ABORT_IF_FALSE(0, "not reached!"); } #endif /* XP_WIN */