Back to index

lightning-sunbird  0.9+nobinonly
nsPluginNativeWindowGtk2.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim:expandtab:shiftwidth=2:tabstop=2:
00003 */
00004 /* ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  *
00018  * The Original Code is mozilla.org code.
00019  *
00020  * The Initial Developer of the Original Code is Sun Microsystems, Inc.
00021  * Portions created by Sun Microsystems are Copyright (C) 2003
00022  * the Sun Microsystems, Inc. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   Robin Lu <robin.lu@sun.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or 
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the NPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the NPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00045 #include "nsDebug.h"
00046 #include "nsPluginNativeWindow.h"
00047 #include "npapi.h"
00048 #include <gtk/gtk.h>
00049 #include <gdk/gdkx.h>
00050 #include <gdk/gdk.h>
00051 #ifdef OJI
00052 #include "plstr.h"
00053 #include "nsIPlugin.h"
00054 #include "nsIPluginHost.h"
00055 
00056 static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID);
00057 #endif
00058 
00059 class nsPluginNativeWindowGtk2 : public nsPluginNativeWindow {
00060 public: 
00061   nsPluginNativeWindowGtk2();
00062   virtual ~nsPluginNativeWindowGtk2();
00063 
00064   virtual nsresult CallSetWindow(nsCOMPtr<nsIPluginInstance> &aPluginInstance);
00065 private:
00066   GtkWidget*  mGtkSocket;
00067   nsresult  CreateXEmbedWindow();
00068   void      SetAllocation();
00069   PRBool    CanGetValueFromPlugin(nsCOMPtr<nsIPluginInstance> &aPluginInstance);
00070 };
00071 
00072 static gboolean plug_removed_cb   (GtkWidget *widget, gpointer data);
00073 
00074 nsPluginNativeWindowGtk2::nsPluginNativeWindowGtk2() : nsPluginNativeWindow()
00075 {
00076   // initialize the struct fields
00077   window = nsnull; 
00078   x = 0; 
00079   y = 0; 
00080   width = 0; 
00081   height = 0; 
00082   memset(&clipRect, 0, sizeof(clipRect));
00083   ws_info = nsnull;
00084   type = nsPluginWindowType_Window;
00085   mGtkSocket = 0;
00086 }
00087 
00088 nsPluginNativeWindowGtk2::~nsPluginNativeWindowGtk2() 
00089 {
00090   if(mGtkSocket) {
00091     gtk_widget_destroy(mGtkSocket);
00092     mGtkSocket = 0;
00093   }
00094 }
00095 
00096 nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
00097 {
00098   NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
00099   *aPluginNativeWindow = new nsPluginNativeWindowGtk2();
00100   return *aPluginNativeWindow ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00101 }
00102 
00103 nsresult PLUG_DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
00104 {
00105   NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
00106   nsPluginNativeWindowGtk2 *p = (nsPluginNativeWindowGtk2 *)aPluginNativeWindow;
00107   delete p;
00108   return NS_OK;
00109 }
00110 
00111 nsresult nsPluginNativeWindowGtk2::CallSetWindow(nsCOMPtr<nsIPluginInstance> &aPluginInstance)
00112 {
00113   if(aPluginInstance) {
00114     nsresult rv;
00115     PRBool val = PR_FALSE;
00116     if(!mGtkSocket) {
00117       if (CanGetValueFromPlugin(aPluginInstance))
00118         rv = aPluginInstance->GetValue
00119                ((nsPluginInstanceVariable)NPPVpluginNeedsXEmbed, &val);
00120     }
00121 #ifdef DEBUG
00122     printf("nsPluginNativeWindowGtk2: NPPVpluginNeedsXEmbed=%d\n", val);
00123 #endif
00124     if(val) {
00125       CreateXEmbedWindow();
00126     }
00127 
00128     if(mGtkSocket) {
00129       // Make sure to resize and re-place the window if required
00130       SetAllocation();
00131       window = (nsPluginPort *)gtk_socket_get_id(GTK_SOCKET(mGtkSocket));
00132     }
00133 #ifdef DEBUG
00134     printf("nsPluginNativeWindowGtk2: call SetWindow with xid=%p\n", (void *)window);
00135 #endif
00136     aPluginInstance->SetWindow(this);
00137   }
00138   else if (mPluginInstance)
00139     mPluginInstance->SetWindow(nsnull);
00140 
00141   SetPluginInstance(aPluginInstance);
00142   return NS_OK;
00143 }
00144 
00145 nsresult nsPluginNativeWindowGtk2::CreateXEmbedWindow() {
00146   if(!mGtkSocket) {
00147     GdkWindow *win = gdk_window_lookup((XID)window);
00148     mGtkSocket = gtk_socket_new();
00149 
00150     //attach the socket to the container widget
00151     gtk_widget_set_parent_window(mGtkSocket, win);
00152 
00153     // Make sure to handle the plug_removed signal.  If we don't the
00154     // socket will automatically be destroyed when the plug is
00155     // removed, which means we're destroying it more than once.
00156     // SYNTAX ERROR.
00157     g_signal_connect(mGtkSocket, "plug_removed",
00158                      G_CALLBACK(plug_removed_cb), NULL);
00159 
00160     gpointer user_data = NULL;
00161     gdk_window_get_user_data(win, &user_data);
00162 
00163     GtkContainer *container = GTK_CONTAINER(user_data);
00164     gtk_container_add(container, mGtkSocket);
00165     gtk_widget_realize(mGtkSocket);
00166 
00167     // Resize before we show
00168     SetAllocation();
00169 
00170     gtk_widget_show(mGtkSocket);
00171 
00172     gdk_flush();
00173     window = (nsPluginPort *)gtk_socket_get_id(GTK_SOCKET(mGtkSocket));
00174   }
00175 
00176   return NS_OK;
00177 }
00178 
00179 void nsPluginNativeWindowGtk2::SetAllocation() {
00180   if (!mGtkSocket)
00181     return;
00182 
00183   GtkAllocation new_allocation;
00184   new_allocation.x = 0;
00185   new_allocation.y = 0;
00186   new_allocation.width = width;
00187   new_allocation.height = height;
00188   gtk_widget_size_allocate(mGtkSocket, &new_allocation);
00189 }
00190 
00191 PRBool nsPluginNativeWindowGtk2::CanGetValueFromPlugin(nsCOMPtr<nsIPluginInstance> &aPluginInstance)
00192 {
00193 #ifdef OJI
00194   if(aPluginInstance) {
00195     nsresult rv;
00196     nsCOMPtr<nsIPluginInstancePeer> peer;
00197 
00198     rv = aPluginInstance->GetPeer(getter_AddRefs(peer));
00199     if (NS_SUCCEEDED(rv) && peer) {
00200       const char *aMimeType = nsnull;
00201 
00202       peer->GetMIMEType((nsMIMEType*)&aMimeType);
00203       if (aMimeType &&
00204           (PL_strncasecmp(aMimeType, "application/x-java-vm", 21) == 0 ||
00205            PL_strncasecmp(aMimeType, "application/x-java-applet", 25) == 0)) {
00206         nsCOMPtr<nsIPluginHost> pluginHost = do_GetService(kPluginManagerCID, &rv);
00207         if (NS_SUCCEEDED(rv) && pluginHost) {
00208           nsIPlugin* pluginFactory = NULL;
00209 
00210           rv = pluginHost->GetPluginFactory("application/x-java-vm", &pluginFactory);
00211           if (NS_SUCCEEDED(rv) && pluginFactory) {
00212             const char * jpiDescription;
00213 
00214             pluginFactory->GetValue(nsPluginVariable_DescriptionString, (void*)&jpiDescription);
00220             if (PL_strncasecmp(jpiDescription, "Java(TM) Plug-in", 16) == 0) {
00221               // Java Plugin support Xembed from JRE 1.5
00222               if (PL_strcasecmp(jpiDescription + 17, "1.5") < 0)
00223                 return PR_FALSE;
00224             }
00225             if (PL_strncasecmp(jpiDescription, "<a href=\"http://www.blackdown.org/java-linux.html\">", 51) == 0) {
00226               // Java Plugin support Xembed from JRE 1.5
00227               if (PL_strcasecmp(jpiDescription + 92, "1.5") < 0)
00228                 return PR_FALSE;
00229             }
00230             if (PL_strncasecmp(jpiDescription, "IBM Java(TM) Plug-in", 20) == 0) {
00231               // Java Plugin support Xembed from JRE 1.5
00232               if (PL_strcasecmp(jpiDescription + 27, "1.5") < 0)
00233                 return PR_FALSE;
00234             }
00235           }
00236         }
00237       }
00238     }
00239   }
00240 #endif
00241 
00242   return PR_TRUE;
00243 }
00244 
00245 /* static */
00246 gboolean
00247 plug_removed_cb (GtkWidget *widget, gpointer data)
00248 {
00249   // Gee, thanks for the info!
00250   return TRUE;
00251 }
00252 
00253