From 8aa982571732eebf7147400969ee5e93e3bf0609 Mon Sep 17 00:00:00 2001 From: "markh%activestate.com" Date: Thu, 22 Feb 2001 11:03:16 +0000 Subject: [PATCH] New plugin sample. Shows how to use native widgets and events in a plugin. Not part of the build. git-svn-id: svn://10.0.0.236/trunk@87661 18797224-902f-48f8-a5cc-f745e15eee43 --- .../plugin/samples/testevents/Makefile | 55 ++ .../plugin/samples/testevents/Makefile.in | 55 ++ .../plugin/samples/testevents/README.txt | 47 + .../samples/testevents/SimpleEventsTest.html | 41 + .../plugin/samples/testevents/makefile.win | 84 ++ .../plugin/samples/testevents/npevents.cpp | 846 ++++++++++++++++++ .../testevents/nsIEventsPluginInstance.idl | 31 + mozilla/modules/plugin/testevents/Makefile | 55 ++ mozilla/modules/plugin/testevents/Makefile.in | 55 ++ mozilla/modules/plugin/testevents/README.txt | 47 + .../plugin/testevents/SimpleEventsTest.html | 41 + .../modules/plugin/testevents/makefile.win | 84 ++ .../modules/plugin/testevents/npevents.cpp | 846 ++++++++++++++++++ .../testevents/nsIEventsPluginInstance.idl | 31 + 14 files changed, 2318 insertions(+) create mode 100644 mozilla/modules/plugin/samples/testevents/Makefile create mode 100644 mozilla/modules/plugin/samples/testevents/Makefile.in create mode 100644 mozilla/modules/plugin/samples/testevents/README.txt create mode 100644 mozilla/modules/plugin/samples/testevents/SimpleEventsTest.html create mode 100644 mozilla/modules/plugin/samples/testevents/makefile.win create mode 100644 mozilla/modules/plugin/samples/testevents/npevents.cpp create mode 100644 mozilla/modules/plugin/samples/testevents/nsIEventsPluginInstance.idl create mode 100644 mozilla/modules/plugin/testevents/Makefile create mode 100644 mozilla/modules/plugin/testevents/Makefile.in create mode 100644 mozilla/modules/plugin/testevents/README.txt create mode 100644 mozilla/modules/plugin/testevents/SimpleEventsTest.html create mode 100644 mozilla/modules/plugin/testevents/makefile.win create mode 100644 mozilla/modules/plugin/testevents/npevents.cpp create mode 100644 mozilla/modules/plugin/testevents/nsIEventsPluginInstance.idl diff --git a/mozilla/modules/plugin/samples/testevents/Makefile b/mozilla/modules/plugin/samples/testevents/Makefile new file mode 100644 index 00000000000..29338f9e639 --- /dev/null +++ b/mozilla/modules/plugin/samples/testevents/Makefile @@ -0,0 +1,55 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 was written by Neil Hodson. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Mark Hammond +# + +DEPTH = ../../.. +topsrcdir = ../../.. +srcdir = . +VPATH = . + +include $(DEPTH)/config/autoconf.mk + +MODULE = npevents +LIBRARY_NAME = npevents +IS_COMPONENT = 1 +REQUIRES = xpcom plugin + +XPIDLSRCS = nsIEventsPluginInstance.idl + +CPPSRCS = npevents.cpp + +LOCAL_INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../public + +EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_XPCOM_LIBS) -L$(DIST)/lib + +ifdef MOZ_ENABLE_GTK +EXTRA_DSO_LDOPTS += -lgtksuperwin +endif + +EXTRA_DSO_LDOPTS += $(TK_LIBS) + +include $(topsrcdir)/config/rules.mk + +CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS) + +install:: + $(INSTALL) SimpleEventsTest.html $(DIST)/bin/res/samples + diff --git a/mozilla/modules/plugin/samples/testevents/Makefile.in b/mozilla/modules/plugin/samples/testevents/Makefile.in new file mode 100644 index 00000000000..82c77baaa7b --- /dev/null +++ b/mozilla/modules/plugin/samples/testevents/Makefile.in @@ -0,0 +1,55 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 was written by Neil Hodson. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Mark Hammond +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = npevents +LIBRARY_NAME = npevents +IS_COMPONENT = 1 +REQUIRES = xpcom plugin + +XPIDLSRCS = nsIEventsPluginInstance.idl + +CPPSRCS = npevents.cpp + +LOCAL_INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../public + +EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_XPCOM_LIBS) -L$(DIST)/lib + +ifdef MOZ_ENABLE_GTK +EXTRA_DSO_LDOPTS += -lgtksuperwin +endif + +EXTRA_DSO_LDOPTS += $(TK_LIBS) + +include $(topsrcdir)/config/rules.mk + +CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS) + +install:: + $(INSTALL) SimpleEventsTest.html $(DIST)/bin/res/samples + diff --git a/mozilla/modules/plugin/samples/testevents/README.txt b/mozilla/modules/plugin/samples/testevents/README.txt new file mode 100644 index 00000000000..ec42ab55414 --- /dev/null +++ b/mozilla/modules/plugin/samples/testevents/README.txt @@ -0,0 +1,47 @@ +README for the plugin event sample. + +INTENT: +------- +The intent of this plugin is to demonstrate how to implement a +"real", native control as a plugin. + +This sample shows how a plugin can sit "nicely" with the Mozilla event +framework - for example, getting and losing focus, and allowing keyboard, +mouse and resize events to be either consumed or passed on at the +plugin's discretion. + +In this sample, we create a standard "edit" control using the +platform's native edit widget. Obviously if you really needed a simple +edit control, you would use a standard HTML or XUL widget - but a native +edit control was chosen for this demonstration as it is generally a simple +native widget, and allows us to concentrate on the event interaction. + +WINDOWS NOTES: +-------------- +A standard Windows edit control is created and subclassed. All keyboard and +mouse messages are passed back to Mozilla itself rather than passed to the +edit control. These messages then wind themselves back around the event +framework, and end up as calls to nsIPlugin::HandleEvent() calls. + +If we let the keyboard messages go directly to the edit control, +we have no way of allowing the keystrokes we _dont_ want to be passed back. If +we let the mouse messages go directly to the control, we don't interact correctly +with focus. + +PROBLEMS: +* Plugins on Windows don't have event messages. +* Plugins on Windows dont have key-pressed messages (only keyup and down) +* Focus interaction is not correct (probably need a focus event) + + +LINUX NOTES: +----------- +A standard Gtk edit control is used. + +PROBLEMS: +* Resizing is messed up, but likely because we don't understand Gtk's sizing +model. + +MAC NOTES: +---------- +No Mac support at all. diff --git a/mozilla/modules/plugin/samples/testevents/SimpleEventsTest.html b/mozilla/modules/plugin/samples/testevents/SimpleEventsTest.html new file mode 100644 index 00000000000..15afe182e78 --- /dev/null +++ b/mozilla/modules/plugin/samples/testevents/SimpleEventsTest.html @@ -0,0 +1,41 @@ + + + +Mozilla Plugin with Events Sample + + + + + + + +
+
+ + +
+ +
+

This for demonstrates a native widget working with the Mozilla plugin +architecture

+

On each platform, a native editor widget is used. Currently, not much works in +terms of mouse, focus or keystroke handling.

+
+ + diff --git a/mozilla/modules/plugin/samples/testevents/makefile.win b/mozilla/modules/plugin/samples/testevents/makefile.win new file mode 100644 index 00000000000..71feda387f7 --- /dev/null +++ b/mozilla/modules/plugin/samples/testevents/makefile.win @@ -0,0 +1,84 @@ +# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + + +MODULE = npevents + +LIBRARY_NAME = npevents + +DEPTH = ..\..\.. + + +XPIDLSRCS = \ + .\nsIEventsPluginInstance.idl \ + $(NULL) + +OBJS = .\$(OBJDIR)\npevents.obj + +JDIRS = . + + +MAKE_OBJ_TYPE=DLL +#//------------------------------------------------------------------------ +#// +#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...) +#// +#//------------------------------------------------------------------------ +DLLNAME=npevents.dll +PDBFILE=npevents.pdb +MAPFILE=npevents.map + +#//------------------------------------------------------------------------ +#// +#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...) +#// (these must be defined before the common makefiles are included) +#// +#//------------------------------------------------------------------------ + +DLL=.\$(OBJDIR)\$(DLLNAME) +MAPFILE= npevents.map + + +#//------------------------------------------------------------------------ +#// +#// Define any local options for the make tools +#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS) +#// +#//------------------------------------------------------------------------ +LLIBS=$(LLIBS) $(LIBNSPR) $(DIST)\lib\xpcom.lib +# clobber and clobber_all will remove the following garbage: +GARBAGE = $(GARBAGE) _gen + +#//------------------------------------------------------------------------ +#// +#// Include the common makefile rules +#// +#//------------------------------------------------------------------------ +include <$(DEPTH)/config/rules.mak> + +LINCS=$(LINCS) -I$(PUBLIC)\plugin -I$(PUBLIC)\xpcom -I$(PUBLIC)\java -I$(PUBLIC)\plugimpl -I$(PUBLIC)\raptor -I_jri + +!ifdef NEW_PLUGIN_STREAM_API +LCFLAGS = $(LCFLAGS) -DNEW_PLUGIN_STREAM_API +!endif + +install:: $(DLL) + $(MAKE_INSTALL) $(OBJDIR)\npevents.dll $(DIST)\bin\components diff --git a/mozilla/modules/plugin/samples/testevents/npevents.cpp b/mozilla/modules/plugin/samples/testevents/npevents.cpp new file mode 100644 index 00000000000..10e6395b4f9 --- /dev/null +++ b/mozilla/modules/plugin/samples/testevents/npevents.cpp @@ -0,0 +1,846 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 was developed by ActiveState, and + * implemented by . + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Neil Hodgson + * Mark Hammond + */ + +// 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); + + static NS_METHOD + UnregisterSelf(nsIComponentManager* aCompMgr, + nsIFile* aPath, + const char* aRegistryLocation); + + + 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); + nsresult PlatformSetWindow(nsPluginWindow* window); + void PlatformResetWindow(); + PRInt16 PlatformHandleEvent(nsPluginEvent* event); + + void SetMode(nsPluginMode mode) { fMode = mode; } + +protected: + //////////////////////////////////////////////////////////////////////////// + // Implementation methods + void Resize(); + + // 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 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) +{ + nsresult rv; + + nsIPluginManager* pm; + rv = nsServiceManager::GetService(kPluginManagerCID, NS_GET_IID(nsIPluginManager), + NS_REINTERPRET_CAST(nsISupports**, &pm)); + 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) +{ + nsresult rv; + + nsIPluginManager* pm; + rv = nsServiceManager::GetService(kPluginManagerCID, NS_GET_IID(nsIPluginManager), + NS_REINTERPRET_CAST(nsISupports**, &pm)); + 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) +{ + NS_INIT_REFCNT(); + 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_FAILED(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; + + /* + * 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 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_) { + NS_INIT_REFCNT(); +#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 + +void EventsPluginInstance::Resize() { +#ifdef XP_WIN + 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); +#endif +} + +// 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. + fPlatform.moz_box = 0; + return NS_OK; +} + +nsresult EventsPluginInstance::PlatformSetWindow(nsPluginWindow* window) { +#ifdef EVENTSPLUGIN_DEBUG + printf("EventsPluginInstance::PlatformSetWindow %p\n", window); +#endif + if (window == NULL || window->window == NULL) + return NS_ERROR_NULL_POINTER; + + if (!wChild) { + + Window x_window = (Window)window->window; + printf("EventsPluginInstance::PlatformSetWindow x %lx\n", x_window); + GdkWindow *gdk_window = (GdkWindow *)gdk_xid_table_lookup(x_window); + printf("EventsPluginInstance::PlatformSetWindow g %p\n", gdk_window); + if (!gdk_window) { + fprintf(stderr, "NO WINDOW!!!\n"); + return NS_OK; + } + 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); + } else { + // Possible resize + //int width = window->width; + //int height = window->height; + //printf("Possible resize %d %d\n", width, height); + } + + //int width = window->width; + //int height = window->height; + //printf("Possible resize %d %d\n", width, height); + //gdk_widget_set_usize(fPlatform.moz_box, width, height); + //gdk_window_resize ((GdkWindow *)fPlatform.moz_box, width, height); + return NS_OK; +} + +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::PlatformSetWindow(nsPluginWindow* window) { +#ifdef EVENTSPLUGIN_DEBUG + printf("EventsPluginInstance::PlatformSetWindow %p\n", window); +#endif + if ( fWindow != NULL ) { /* If we already have a window, clean + * it up before trying to subclass + * the new window. */ + if ( window && window->window && wMain == (HWND)window->window ) { + /* The new window is the same as the old one. Exit now. */ + 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 HWND and wndproc. + wMain = (HWND)window->window; + 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, // 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); + + /* Finally resize and clear the new window, and we are done. */ + Resize(); + ::InvalidateRect(wMain, NULL, TRUE); + ::UpdateWindow(wMain); + } + return NS_OK; +} + +int16 EventsPluginInstance::PlatformHandleEvent(nsPluginEvent * /*event*/) { + return NS_OK; +} + +void EventsPluginInstance::PlatformResetWindow() { + fPlatform.fParentWindowProc = NULL; + ::SetWindowLong(wChild, GWL_WNDPROC, (LONG)fPlatform.fOldChildWindowProc); + fPlatform.fOldChildWindowProc = NULL; + wChild = NULL; + wMain = NULL; +} +/* 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 */ diff --git a/mozilla/modules/plugin/samples/testevents/nsIEventsPluginInstance.idl b/mozilla/modules/plugin/samples/testevents/nsIEventsPluginInstance.idl new file mode 100644 index 00000000000..ba536e51c85 --- /dev/null +++ b/mozilla/modules/plugin/samples/testevents/nsIEventsPluginInstance.idl @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 was developed by ActiveState, and + * implemented by Neil Hodgson. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Mark Hammond + */ + +#include "nsISupports.idl" + +[scriptable, uuid(306743A0-976E-478a-93AA-01BDDADC77E9)] +interface nsIEventsSampleInstance: nsISupports { + attribute string val; +}; + diff --git a/mozilla/modules/plugin/testevents/Makefile b/mozilla/modules/plugin/testevents/Makefile new file mode 100644 index 00000000000..29338f9e639 --- /dev/null +++ b/mozilla/modules/plugin/testevents/Makefile @@ -0,0 +1,55 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 was written by Neil Hodson. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Mark Hammond +# + +DEPTH = ../../.. +topsrcdir = ../../.. +srcdir = . +VPATH = . + +include $(DEPTH)/config/autoconf.mk + +MODULE = npevents +LIBRARY_NAME = npevents +IS_COMPONENT = 1 +REQUIRES = xpcom plugin + +XPIDLSRCS = nsIEventsPluginInstance.idl + +CPPSRCS = npevents.cpp + +LOCAL_INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../public + +EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_XPCOM_LIBS) -L$(DIST)/lib + +ifdef MOZ_ENABLE_GTK +EXTRA_DSO_LDOPTS += -lgtksuperwin +endif + +EXTRA_DSO_LDOPTS += $(TK_LIBS) + +include $(topsrcdir)/config/rules.mk + +CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS) + +install:: + $(INSTALL) SimpleEventsTest.html $(DIST)/bin/res/samples + diff --git a/mozilla/modules/plugin/testevents/Makefile.in b/mozilla/modules/plugin/testevents/Makefile.in new file mode 100644 index 00000000000..82c77baaa7b --- /dev/null +++ b/mozilla/modules/plugin/testevents/Makefile.in @@ -0,0 +1,55 @@ +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 was written by Neil Hodson. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# Mark Hammond +# + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = npevents +LIBRARY_NAME = npevents +IS_COMPONENT = 1 +REQUIRES = xpcom plugin + +XPIDLSRCS = nsIEventsPluginInstance.idl + +CPPSRCS = npevents.cpp + +LOCAL_INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../public + +EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_XPCOM_LIBS) -L$(DIST)/lib + +ifdef MOZ_ENABLE_GTK +EXTRA_DSO_LDOPTS += -lgtksuperwin +endif + +EXTRA_DSO_LDOPTS += $(TK_LIBS) + +include $(topsrcdir)/config/rules.mk + +CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS) + +install:: + $(INSTALL) SimpleEventsTest.html $(DIST)/bin/res/samples + diff --git a/mozilla/modules/plugin/testevents/README.txt b/mozilla/modules/plugin/testevents/README.txt new file mode 100644 index 00000000000..ec42ab55414 --- /dev/null +++ b/mozilla/modules/plugin/testevents/README.txt @@ -0,0 +1,47 @@ +README for the plugin event sample. + +INTENT: +------- +The intent of this plugin is to demonstrate how to implement a +"real", native control as a plugin. + +This sample shows how a plugin can sit "nicely" with the Mozilla event +framework - for example, getting and losing focus, and allowing keyboard, +mouse and resize events to be either consumed or passed on at the +plugin's discretion. + +In this sample, we create a standard "edit" control using the +platform's native edit widget. Obviously if you really needed a simple +edit control, you would use a standard HTML or XUL widget - but a native +edit control was chosen for this demonstration as it is generally a simple +native widget, and allows us to concentrate on the event interaction. + +WINDOWS NOTES: +-------------- +A standard Windows edit control is created and subclassed. All keyboard and +mouse messages are passed back to Mozilla itself rather than passed to the +edit control. These messages then wind themselves back around the event +framework, and end up as calls to nsIPlugin::HandleEvent() calls. + +If we let the keyboard messages go directly to the edit control, +we have no way of allowing the keystrokes we _dont_ want to be passed back. If +we let the mouse messages go directly to the control, we don't interact correctly +with focus. + +PROBLEMS: +* Plugins on Windows don't have event messages. +* Plugins on Windows dont have key-pressed messages (only keyup and down) +* Focus interaction is not correct (probably need a focus event) + + +LINUX NOTES: +----------- +A standard Gtk edit control is used. + +PROBLEMS: +* Resizing is messed up, but likely because we don't understand Gtk's sizing +model. + +MAC NOTES: +---------- +No Mac support at all. diff --git a/mozilla/modules/plugin/testevents/SimpleEventsTest.html b/mozilla/modules/plugin/testevents/SimpleEventsTest.html new file mode 100644 index 00000000000..15afe182e78 --- /dev/null +++ b/mozilla/modules/plugin/testevents/SimpleEventsTest.html @@ -0,0 +1,41 @@ + + + +Mozilla Plugin with Events Sample + + + + + + + +
+
+ + +
+ +
+

This for demonstrates a native widget working with the Mozilla plugin +architecture

+

On each platform, a native editor widget is used. Currently, not much works in +terms of mouse, focus or keystroke handling.

+
+ + diff --git a/mozilla/modules/plugin/testevents/makefile.win b/mozilla/modules/plugin/testevents/makefile.win new file mode 100644 index 00000000000..71feda387f7 --- /dev/null +++ b/mozilla/modules/plugin/testevents/makefile.win @@ -0,0 +1,84 @@ +# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# The contents of this file are subject to the Netscape 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/NPL/ +# +# 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 Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + + +MODULE = npevents + +LIBRARY_NAME = npevents + +DEPTH = ..\..\.. + + +XPIDLSRCS = \ + .\nsIEventsPluginInstance.idl \ + $(NULL) + +OBJS = .\$(OBJDIR)\npevents.obj + +JDIRS = . + + +MAKE_OBJ_TYPE=DLL +#//------------------------------------------------------------------------ +#// +#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...) +#// +#//------------------------------------------------------------------------ +DLLNAME=npevents.dll +PDBFILE=npevents.pdb +MAPFILE=npevents.map + +#//------------------------------------------------------------------------ +#// +#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...) +#// (these must be defined before the common makefiles are included) +#// +#//------------------------------------------------------------------------ + +DLL=.\$(OBJDIR)\$(DLLNAME) +MAPFILE= npevents.map + + +#//------------------------------------------------------------------------ +#// +#// Define any local options for the make tools +#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS) +#// +#//------------------------------------------------------------------------ +LLIBS=$(LLIBS) $(LIBNSPR) $(DIST)\lib\xpcom.lib +# clobber and clobber_all will remove the following garbage: +GARBAGE = $(GARBAGE) _gen + +#//------------------------------------------------------------------------ +#// +#// Include the common makefile rules +#// +#//------------------------------------------------------------------------ +include <$(DEPTH)/config/rules.mak> + +LINCS=$(LINCS) -I$(PUBLIC)\plugin -I$(PUBLIC)\xpcom -I$(PUBLIC)\java -I$(PUBLIC)\plugimpl -I$(PUBLIC)\raptor -I_jri + +!ifdef NEW_PLUGIN_STREAM_API +LCFLAGS = $(LCFLAGS) -DNEW_PLUGIN_STREAM_API +!endif + +install:: $(DLL) + $(MAKE_INSTALL) $(OBJDIR)\npevents.dll $(DIST)\bin\components diff --git a/mozilla/modules/plugin/testevents/npevents.cpp b/mozilla/modules/plugin/testevents/npevents.cpp new file mode 100644 index 00000000000..10e6395b4f9 --- /dev/null +++ b/mozilla/modules/plugin/testevents/npevents.cpp @@ -0,0 +1,846 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 was developed by ActiveState, and + * implemented by . + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Neil Hodgson + * Mark Hammond + */ + +// 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); + + static NS_METHOD + UnregisterSelf(nsIComponentManager* aCompMgr, + nsIFile* aPath, + const char* aRegistryLocation); + + + 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); + nsresult PlatformSetWindow(nsPluginWindow* window); + void PlatformResetWindow(); + PRInt16 PlatformHandleEvent(nsPluginEvent* event); + + void SetMode(nsPluginMode mode) { fMode = mode; } + +protected: + //////////////////////////////////////////////////////////////////////////// + // Implementation methods + void Resize(); + + // 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 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) +{ + nsresult rv; + + nsIPluginManager* pm; + rv = nsServiceManager::GetService(kPluginManagerCID, NS_GET_IID(nsIPluginManager), + NS_REINTERPRET_CAST(nsISupports**, &pm)); + 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) +{ + nsresult rv; + + nsIPluginManager* pm; + rv = nsServiceManager::GetService(kPluginManagerCID, NS_GET_IID(nsIPluginManager), + NS_REINTERPRET_CAST(nsISupports**, &pm)); + 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) +{ + NS_INIT_REFCNT(); + 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_FAILED(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; + + /* + * 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 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_) { + NS_INIT_REFCNT(); +#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 + +void EventsPluginInstance::Resize() { +#ifdef XP_WIN + 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); +#endif +} + +// 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. + fPlatform.moz_box = 0; + return NS_OK; +} + +nsresult EventsPluginInstance::PlatformSetWindow(nsPluginWindow* window) { +#ifdef EVENTSPLUGIN_DEBUG + printf("EventsPluginInstance::PlatformSetWindow %p\n", window); +#endif + if (window == NULL || window->window == NULL) + return NS_ERROR_NULL_POINTER; + + if (!wChild) { + + Window x_window = (Window)window->window; + printf("EventsPluginInstance::PlatformSetWindow x %lx\n", x_window); + GdkWindow *gdk_window = (GdkWindow *)gdk_xid_table_lookup(x_window); + printf("EventsPluginInstance::PlatformSetWindow g %p\n", gdk_window); + if (!gdk_window) { + fprintf(stderr, "NO WINDOW!!!\n"); + return NS_OK; + } + 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); + } else { + // Possible resize + //int width = window->width; + //int height = window->height; + //printf("Possible resize %d %d\n", width, height); + } + + //int width = window->width; + //int height = window->height; + //printf("Possible resize %d %d\n", width, height); + //gdk_widget_set_usize(fPlatform.moz_box, width, height); + //gdk_window_resize ((GdkWindow *)fPlatform.moz_box, width, height); + return NS_OK; +} + +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::PlatformSetWindow(nsPluginWindow* window) { +#ifdef EVENTSPLUGIN_DEBUG + printf("EventsPluginInstance::PlatformSetWindow %p\n", window); +#endif + if ( fWindow != NULL ) { /* If we already have a window, clean + * it up before trying to subclass + * the new window. */ + if ( window && window->window && wMain == (HWND)window->window ) { + /* The new window is the same as the old one. Exit now. */ + 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 HWND and wndproc. + wMain = (HWND)window->window; + 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, // 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); + + /* Finally resize and clear the new window, and we are done. */ + Resize(); + ::InvalidateRect(wMain, NULL, TRUE); + ::UpdateWindow(wMain); + } + return NS_OK; +} + +int16 EventsPluginInstance::PlatformHandleEvent(nsPluginEvent * /*event*/) { + return NS_OK; +} + +void EventsPluginInstance::PlatformResetWindow() { + fPlatform.fParentWindowProc = NULL; + ::SetWindowLong(wChild, GWL_WNDPROC, (LONG)fPlatform.fOldChildWindowProc); + fPlatform.fOldChildWindowProc = NULL; + wChild = NULL; + wMain = NULL; +} +/* 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 */ diff --git a/mozilla/modules/plugin/testevents/nsIEventsPluginInstance.idl b/mozilla/modules/plugin/testevents/nsIEventsPluginInstance.idl new file mode 100644 index 00000000000..ba536e51c85 --- /dev/null +++ b/mozilla/modules/plugin/testevents/nsIEventsPluginInstance.idl @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * 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 was developed by ActiveState, and + * implemented by Neil Hodgson. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Mark Hammond + */ + +#include "nsISupports.idl" + +[scriptable, uuid(306743A0-976E-478a-93AA-01BDDADC77E9)] +interface nsIEventsSampleInstance: nsISupports { + attribute string val; +}; +