From 19186c65469d244df7f8c29e9bf04eb0d2b97c95 Mon Sep 17 00:00:00 2001 From: "robin.lu%sun.com" Date: Tue, 16 Sep 2003 01:44:41 +0000 Subject: [PATCH] patch for bug 189229 : xembed for plugins patched by robin.lu@sun.com r=joshua.xia@sun.com sr=blizzard@mozilla.org git-svn-id: svn://10.0.0.236/trunk@146940 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/modules/plugin/base/public/npapi.h | 17 +- .../modules/plugin/base/public/nsplugindefs.h | 6 +- mozilla/modules/plugin/base/src/Makefile.in | 5 + .../modules/plugin/base/src/ns4xPlugin.cpp | 35 ++++ .../plugin/base/src/ns4xPluginInstance.cpp | 29 +++- .../plugin/base/src/nsPluginHostImpl.cpp | 27 ++- .../base/src/nsPluginNativeWindowGtk2.cpp | 157 ++++++++++++++++++ mozilla/widget/src/gtk2/Makefile.in | 2 + mozilla/widget/src/gtk2/nsWindow.cpp | 23 ++- mozilla/widget/src/gtk2/nsWindow.h | 10 +- 10 files changed, 284 insertions(+), 27 deletions(-) create mode 100644 mozilla/modules/plugin/base/src/nsPluginNativeWindowGtk2.cpp diff --git a/mozilla/modules/plugin/base/public/npapi.h b/mozilla/modules/plugin/base/public/npapi.h index 6cfc252048b..70739f27d32 100644 --- a/mozilla/modules/plugin/base/public/npapi.h +++ b/mozilla/modules/plugin/base/public/npapi.h @@ -38,7 +38,7 @@ /* - * npapi.h $Revision: 3.31 $ + * npapi.h $Revision: 3.32 $ * Netscape client plug-in API spec */ @@ -387,7 +387,8 @@ typedef enum { /* 12 and over are available on Mozilla builds starting with 0.9.9 */ NPPVjavascriptPushCallerBool = 12, - NPPVpluginKeepLibraryInMemory = 13 /* available in Mozilla 1.0 */ + NPPVpluginKeepLibraryInMemory = 13, /* available in Mozilla 1.0 */ + NPPVpluginNeedsXEmbed = 14 } NPPVariable; /* @@ -404,9 +405,19 @@ typedef enum { /* 10 and over are available on Mozilla builds starting with 0.9.4 */ NPNVserviceManager = (10 | NP_ABI_MASK), NPNVDOMElement = (11 | NP_ABI_MASK), /* available in Mozilla 1.2 */ - NPNVDOMWindow = (12 | NP_ABI_MASK) + NPNVDOMWindow = (12 | NP_ABI_MASK), + NPNVToolkit = (13 | NP_ABI_MASK), + NPNVSupportsXEmbedBool = 14 } NPNVariable; +/* + * The type of Tookkit the widgets use + */ +typedef enum { + NPNVGtk12 = 1, + NPNVGtk2 +} NPNToolkitType; + /* * The type of a NPWindow - it specifies the type of the data structure * returned in the window field. diff --git a/mozilla/modules/plugin/base/public/nsplugindefs.h b/mozilla/modules/plugin/base/public/nsplugindefs.h index 35540c18834..aaaaf4c37f2 100644 --- a/mozilla/modules/plugin/base/public/nsplugindefs.h +++ b/mozilla/modules/plugin/base/public/nsplugindefs.h @@ -188,7 +188,8 @@ enum nsPluginVariable { enum nsPluginManagerVariable { nsPluginManagerVariable_XDisplay = 1, - nsPluginManagerVariable_XtAppContext = 2 + nsPluginManagerVariable_XtAppContext = 2, + nsPluginManagerVariable_SupportsXEmbed = 14 }; enum nsPluginInstancePeerVariable { @@ -203,7 +204,8 @@ enum nsPluginInstanceVariable { nsPluginInstanceVariable_DoCacheBool = 5, nsPluginInstanceVariable_CallSetWindowAfterDestroyBool = 6, nsPluginInstanceVariable_ScriptableInstance = 10, - nsPluginInstanceVariable_ScriptableIID = 11 + nsPluginInstanceVariable_ScriptableIID = 11, + nsPluginInstanceVariable_NeedsXEmbed = 14 }; //////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/modules/plugin/base/src/Makefile.in b/mozilla/modules/plugin/base/src/Makefile.in index 9918422f997..ce5638aa8cc 100644 --- a/mozilla/modules/plugin/base/src/Makefile.in +++ b/mozilla/modules/plugin/base/src/Makefile.in @@ -89,6 +89,10 @@ else ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT))) CPPSRCS += nsPluginsDirDarwin.cpp CPPSRCS += nsPluginNativeWindow.cpp +else +ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) + CPPSRCS += nsPluginsDirUnix.cpp + CPPSRCS += nsPluginNativeWindowGtk2.cpp else CPPSRCS += nsPluginsDirUnix.cpp CPPSRCS += nsPluginNativeWindow.cpp @@ -96,6 +100,7 @@ endif endif endif endif +endif ifneq (,$(filter WINNT Darwin,$(OS_ARCH))) EXTRA_DSO_LIBS += gkgfx diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp index b78052069cd..12b14b13f2c 100644 --- a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp @@ -1225,6 +1225,17 @@ _getvalue(NPP npp, NPNVariable variable, void *result) switch(variable) { #if defined(XP_UNIX) && !defined(XP_MACOSX) case NPNVxDisplay : { +#ifdef MOZ_WIDGET_GTK2 + if(npp) { + ns4xPluginInstance *inst = (ns4xPluginInstance *) npp->ndata; + NPBool rtv = PR_FALSE; + inst->GetValue((nsPluginInstanceVariable)NPPVpluginNeedsXEmbed, &rtv); + if(rtv) { + (*(Display **)result) = GDK_DISPLAY(); + return NPERR_NO_ERROR; + } + } +#endif #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2) // adobe nppdf calls XtGetApplicationNameAndClass(display, &instance, &class) // we have to init Xt toolkit before get XtDisplay @@ -1337,6 +1348,30 @@ _getvalue(NPP npp, NPNVariable variable, void *result) } return NPERR_GENERIC_ERROR; } + + case NPNVToolkit: { +#ifdef MOZ_WIDGET_GTK + *((NPNToolkitType*)result) = NPNVGtk12; +#endif + +#ifdef MOZ_WIDGET_GTK2 + *((NPNToolkitType*)result) = NPNVGtk2; +#endif + + if (result) + return NPERR_NO_ERROR; + + return NPERR_GENERIC_ERROR; + } + + case NPNVSupportsXEmbedBool: { +#ifdef MOZ_WIDGET_GTK2 + *(NPBool*)result = PR_TRUE; +#else + *(NPBool*)result = PR_FALSE; +#endif + return NPERR_NO_ERROR; + } default : return NPERR_GENERIC_ERROR; } } diff --git a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp index 9b031abe6e0..cee50036b11 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp @@ -860,6 +860,7 @@ NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window) NPError error; #if defined (MOZ_WIDGET_GTK) || defined (MOZ_WIDGET_GTK2) + PRBool isXembed = PR_FALSE; // bug 108337, flash plugin on linux doesn't like window->width <= 0 if ((PRInt32) window->width <= 0 || (PRInt32) window->height <= 0) return NS_OK; @@ -881,6 +882,15 @@ NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window) GdkWindow *win = gdk_window_lookup((XID)window->window); if (!win) return NS_ERROR_FAILURE; + gpointer user_data = nsnull; + gdk_window_get_user_data(win, &user_data); + if (user_data) { + GtkWidget* widget = GTK_WIDGET(user_data); + if (GTK_IS_SOCKET(widget)) { + isXembed = PR_TRUE; + } + } + if (!isXembed) { #ifdef NS_DEBUG printf("About to create new xtbin of %i X %i from %p...\n", @@ -929,7 +939,10 @@ NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window) ws->type = 0; // OK, that was a guess!! #ifdef MOZ_X11 ws->depth = gdk_window_get_visual(win)->depth; - ws->display = GTK_XTBIN(mXtBin)->xtdisplay; + if (!isXembed) + ws->display = GTK_XTBIN(mXtBin)->xtdisplay; + else + ws->display = GDK_WINDOW_XDISPLAY(win); ws->visual = GDK_VISUAL_XVISUAL(gdk_window_get_visual(win)); ws->colormap = GDK_COLORMAP_XCOLORMAP(gdk_window_get_colormap(win)); @@ -937,14 +950,16 @@ NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window) #endif } // !window->ws_info - if (!mXtBin) + if (!mXtBin && !isXembed) return NS_ERROR_FAILURE; - // And now point the NPWindow structures window - // to the actual X window - window->window = (nsPluginPort *)GTK_XTBIN(mXtBin)->xtwindow; - - gtk_xtbin_resize(mXtBin, window->width, window->height); + if (!isXembed) { + // And now point the NPWindow structures window + // to the actual X window + window->window = (nsPluginPort *)GTK_XTBIN(mXtBin)->xtwindow; + + gtk_xtbin_resize(mXtBin, window->width, window->height); + } #elif defined(MOZ_WIDGET_XLIB) diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index c3b2c432721..ca1247388fd 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -2095,7 +2095,10 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aCo // If we've got a native window, the let the plugin know // about it. if (window->window) - mInstance->SetWindow(window); + { + nsCOMPtr inst = mInstance; + ((nsPluginNativeWindow*)window)->CallSetWindow(inst); + } } } } @@ -2638,6 +2641,13 @@ NS_IMETHODIMP nsPluginHostImpl::GetValue(nsPluginManagerVariable aVariable, void } } #endif + if (nsPluginManagerVariable_SupportsXEmbed == aVariable) { +#ifdef MOZ_WIDGET_GTK2 + *(NPBool*)aValue = PR_TRUE; +#else + *(NPBool*)aValue = PR_FALSE; +#endif + } return rv; } @@ -3454,7 +3464,10 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateEmbededPlugin(const char *aMimeType, // If we've got a native window, the let the plugin know about it. if (window->window) - instance->SetWindow(window); + { + nsCOMPtr inst = instance; + ((nsPluginNativeWindow*)window)->CallSetWindow(inst); + } // create an initial stream with data // don't make the stream if it's a java applet or we don't have SRC or DATA attribute @@ -3596,7 +3609,10 @@ nsresult nsPluginHostImpl::FindStoppedPluginForURL(nsIURI* aURL, // If we've got a native window, the let the plugin know about it. if (window->window) - instance->SetWindow(window); + { + nsCOMPtr inst = instance; + ((nsPluginNativeWindow*)window)->CallSetWindow(inst); + } plugin->setStopped(PR_FALSE); return NS_OK; @@ -6601,7 +6617,10 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request, nsPluginWindow *window = nsnull; owner->GetWindow(window); if (window->window) - mInstance->SetWindow(window); + { + nsCOMPtr inst = mInstance; + ((nsPluginNativeWindow*)window)->CallSetWindow(inst); + } } } diff --git a/mozilla/modules/plugin/base/src/nsPluginNativeWindowGtk2.cpp b/mozilla/modules/plugin/base/src/nsPluginNativeWindowGtk2.cpp new file mode 100644 index 00000000000..1008bfa3235 --- /dev/null +++ b/mozilla/modules/plugin/base/src/nsPluginNativeWindowGtk2.cpp @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:expandtab:shiftwidth=2:tabstop=2: +*/ +/* ***** 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 Sun Microsystems, Inc. + * Portions created by Sun Microsystems are Copyright (C) 2003 + * the Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Robin Lu + * + * 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 NPL, 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 NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * This file is the Gtk2 implementation of plugin native window. + */ + +#include "nsDebug.h" +#include "nsPluginNativeWindow.h" +#include "npapi.h" +#include +#include +#include + +class nsPluginNativeWindowGtk2 : public nsPluginNativeWindow { +public: + nsPluginNativeWindowGtk2(); + virtual ~nsPluginNativeWindowGtk2(); + + virtual nsresult CallSetWindow(nsCOMPtr &aPluginInstance); +private: + GtkWidget* mGtkSocket; + nsresult CreateXEmbedWindow(); +}; + +nsPluginNativeWindowGtk2::nsPluginNativeWindowGtk2() : nsPluginNativeWindow() +{ + // initialize the struct fields + window = nsnull; + x = 0; + y = 0; + width = 0; + height = 0; + memset(&clipRect, 0, sizeof(clipRect)); + ws_info = nsnull; + type = nsPluginWindowType_Window; + mGtkSocket = 0; +} + +nsPluginNativeWindowGtk2::~nsPluginNativeWindowGtk2() +{ + if(mGtkSocket) { + gtk_widget_destroy(mGtkSocket); + mGtkSocket = 0; + } +} + +nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow) +{ + NS_ENSURE_ARG_POINTER(aPluginNativeWindow); + *aPluginNativeWindow = new nsPluginNativeWindowGtk2(); + return *aPluginNativeWindow ? NS_OK : NS_ERROR_OUT_OF_MEMORY; +} + +nsresult PLUG_DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow) +{ + NS_ENSURE_ARG_POINTER(aPluginNativeWindow); + nsPluginNativeWindowGtk2 *p = (nsPluginNativeWindowGtk2 *)aPluginNativeWindow; + delete p; + return NS_OK; +} + +nsresult nsPluginNativeWindowGtk2::CallSetWindow(nsCOMPtr &aPluginInstance) +{ + if(aPluginInstance) { + nsresult rv; + PRBool val = PR_FALSE; + if(!mGtkSocket) { + rv = aPluginInstance->GetValue + ((nsPluginInstanceVariable)NPPVpluginNeedsXEmbed, &val); + } +#ifdef DEBUG + printf("nsPluginNativeWindowGtk2: NPPVpluginNeedsXEmbed=%d\n", &val); +#endif + if(val) { + CreateXEmbedWindow(); + } + if(mGtkSocket) + window = (nsPluginPort *)gtk_socket_get_id(GTK_SOCKET(mGtkSocket)); +#ifdef DEBUG + printf("nsPluginNativeWindowGtk2: call SetWindow with xid=%p\n", window); +#endif + aPluginInstance->SetWindow(this); + } + else if (mPluginInstance) + mPluginInstance->SetWindow(nsnull); + + SetPluginInstance(aPluginInstance); + return NS_OK; +} + +nsresult nsPluginNativeWindowGtk2::CreateXEmbedWindow() { + if(!mGtkSocket) { + GdkWindow *win = gdk_window_lookup((XID)window); + mGtkSocket = gtk_socket_new(); + + //attach the socket to the container widget + gtk_widget_set_parent_window(mGtkSocket, win); + + gpointer user_data = NULL; + gdk_window_get_user_data(win, &user_data); + + GtkContainer *container = GTK_CONTAINER(user_data); + gtk_container_add(container, mGtkSocket); + gtk_widget_realize(mGtkSocket); + + GtkAllocation new_allocation; + new_allocation.x = 0; + new_allocation.y = 0; + new_allocation.width = width; + new_allocation.height = height; + gtk_widget_size_allocate(mGtkSocket, &new_allocation); + gtk_widget_show(mGtkSocket); + + gdk_flush(); + window = (nsPluginPort *)gtk_socket_get_id(GTK_SOCKET(mGtkSocket)); + } + + return NS_OK; +} diff --git a/mozilla/widget/src/gtk2/Makefile.in b/mozilla/widget/src/gtk2/Makefile.in index af8c0645178..398ad5ab631 100644 --- a/mozilla/widget/src/gtk2/Makefile.in +++ b/mozilla/widget/src/gtk2/Makefile.in @@ -39,6 +39,7 @@ REQUIRES = xpcom \ dom \ necko \ uconv \ + gtkxtbin \ xremoteservice CSRCS = \ @@ -72,6 +73,7 @@ SHARED_LIBRARY_LIBS = $(DIST)/lib/libxpwidgets_s.a EXTRA_DSO_LDOPTS += \ $(MOZ_COMPONENT_LIBS) \ -lgkgfx \ + -lgtkxtbin \ $(XLDFLAGS) \ $(XLIBS) \ $(MOZ_GTK2_LIBS) diff --git a/mozilla/widget/src/gtk2/nsWindow.cpp b/mozilla/widget/src/gtk2/nsWindow.cpp index 5c9040a1b67..0e5a4f263bd 100644 --- a/mozilla/widget/src/gtk2/nsWindow.cpp +++ b/mozilla/widget/src/gtk2/nsWindow.cpp @@ -55,6 +55,8 @@ #include #include +#include "gtk2xtbin.h" + #include "nsIPref.h" #include "nsIServiceManager.h" @@ -233,12 +235,12 @@ nsWindow::nsWindow() mIsVisible = PR_FALSE; mRetryPointerGrab = PR_FALSE; mRetryKeyboardGrab = PR_FALSE; - mHasNonXembedPlugin = PR_FALSE; mActivatePending = PR_FALSE; mTransientParent = nsnull; mWindowType = eWindowType_child; mSizeState = nsSizeMode_Normal; mOldFocusWindow = 0; + mPluginType = PluginType_NONE; if (!gGlobalsInitialized) { gGlobalsInitialized = PR_TRUE; @@ -2590,15 +2592,15 @@ nsWindow::SetDefaultIcon(void) } void -nsWindow::SetPluginType(PRBool aIsXembed) +nsWindow::SetPluginType(PluginType aPluginType) { - mHasNonXembedPlugin = !aIsXembed; + mPluginType = aPluginType; } void nsWindow::SetNonXEmbedPluginFocus() { - if (gPluginFocusWindow == this) { + if (gPluginFocusWindow == this || mPluginType!=PluginType_NONXEMBED) { return; } @@ -2654,7 +2656,7 @@ nsWindow::LoseNonXEmbedPluginFocus() // This method is only for the nsWindow which contains a // Non-XEmbed plugin, for example, JAVA plugin. - if (gPluginFocusWindow != this) { + if (gPluginFocusWindow != this || mPluginType!=PluginType_NONXEMBED) { return; } @@ -3246,16 +3248,19 @@ plugin_window_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data gdk_window_get_user_data(plugin_window, &user_data); widget = GTK_WIDGET(user_data); - if (GTK_IS_SOCKET(widget)) { + if (GTK_IS_XTBIN(widget)) { + nswindow->SetPluginType(nsWindow::PluginType_NONXEMBED); + break; + } + else if(GTK_IS_SOCKET(widget)) { + nswindow->SetPluginType(nsWindow::PluginType_XEMBED); break; } } - nswindow->SetPluginType(PR_FALSE); + nswindow->SetPluginType(nsWindow::PluginType_NONXEMBED); return_val = GDK_FILTER_REMOVE; break; case EnterNotify: - // Currently we consider all plugins are non-xembed and calls - // SetNonXEmbedPluginFocus without any checking. nswindow->SetNonXEmbedPluginFocus(); break; case DestroyNotify: diff --git a/mozilla/widget/src/gtk2/nsWindow.h b/mozilla/widget/src/gtk2/nsWindow.h index e431fa92e60..3bab4ddbfa0 100644 --- a/mozilla/widget/src/gtk2/nsWindow.h +++ b/mozilla/widget/src/gtk2/nsWindow.h @@ -235,7 +235,13 @@ public: void GrabKeyboard (void); void ReleaseGrabs (void); - void SetPluginType(PRBool aIsXembed); + enum PluginType { + PluginType_NONE = 0, /* do not have any plugin */ + PluginType_XEMBED, /* the plugin support xembed */ + PluginType_NONXEMBED /* the plugin does not support xembed */ + }; + + void SetPluginType(PluginType aPluginType); void SetNonXEmbedPluginFocus(void); void LoseNonXEmbedPluginFocus(void); @@ -281,11 +287,11 @@ private: mInKeyRepeat : 1, mIsVisible : 1, mRetryPointerGrab : 1, - mHasNonXembedPlugin : 1, mActivatePending : 1, mRetryKeyboardGrab : 1; GtkWindow *mTransientParent; PRInt32 mSizeState; + PluginType mPluginType; #ifdef ACCESSIBILITY nsCOMPtr mRootAccessible;