1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
4 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is mozilla.org code.
19 * The Initial Developer of the Original Code is
20 * Sun Microsystems, Inc.
21 * Portions created by the Initial Developer are Copyright (C) 2003
22 * the Initial Developer. All Rights Reserved.
25 * Robin Lu <robin.lu@sun.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 * This file is the Gtk2 implementation of plugin native window.
46 #include "nsPluginNativeWindow.h"
51 #include "gtk2xtbin.h"
54 #include "nsIPlugin.h"
55 #include "nsIPluginHost.h"
57 static NS_DEFINE_CID(kPluginManagerCID
, NS_PLUGINMANAGER_CID
);
60 class nsPluginNativeWindowGtk2
: public nsPluginNativeWindow
{
62 nsPluginNativeWindowGtk2();
63 virtual ~nsPluginNativeWindowGtk2();
65 virtual nsresult
CallSetWindow(nsCOMPtr
<nsIPluginInstance
> &aPluginInstance
);
67 NPSetWindowCallbackStruct mWsInfo
;
69 * Either a GtkSocket or a special GtkXtBin widget (derived from GtkSocket)
70 * that encapsulates the Xt toolkit within a Gtk Application.
72 GtkWidget
* mSocketWidget
;
73 nsresult
CreateXEmbedWindow();
74 nsresult
CreateXtWindow();
76 PRBool
CanGetValueFromPlugin(nsCOMPtr
<nsIPluginInstance
> &aPluginInstance
);
79 static gboolean
plug_removed_cb (GtkWidget
*widget
, gpointer data
);
81 nsPluginNativeWindowGtk2::nsPluginNativeWindowGtk2() : nsPluginNativeWindow()
83 // initialize the struct fields
89 memset(&clipRect
, 0, sizeof(clipRect
));
91 type
= nsPluginWindowType_Window
;
94 mWsInfo
.display
= nsnull
;
95 mWsInfo
.visual
= nsnull
;
100 nsPluginNativeWindowGtk2::~nsPluginNativeWindowGtk2()
103 gtk_widget_destroy(mSocketWidget
);
107 nsresult
PLUG_NewPluginNativeWindow(nsPluginNativeWindow
** aPluginNativeWindow
)
109 NS_ENSURE_ARG_POINTER(aPluginNativeWindow
);
110 *aPluginNativeWindow
= new nsPluginNativeWindowGtk2();
111 return *aPluginNativeWindow
? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
114 nsresult
PLUG_DeletePluginNativeWindow(nsPluginNativeWindow
* aPluginNativeWindow
)
116 NS_ENSURE_ARG_POINTER(aPluginNativeWindow
);
117 nsPluginNativeWindowGtk2
*p
= (nsPluginNativeWindowGtk2
*)aPluginNativeWindow
;
122 nsresult
nsPluginNativeWindowGtk2::CallSetWindow(nsCOMPtr
<nsIPluginInstance
> &aPluginInstance
)
124 if(aPluginInstance
) {
125 if (type
== nsPluginWindowType_Window
) {
128 PRBool needXEmbed
= PR_FALSE
;
129 if (CanGetValueFromPlugin(aPluginInstance
)) {
130 rv
= aPluginInstance
->GetValue
131 ((nsPluginInstanceVariable
)NPPVpluginNeedsXEmbed
, &needXEmbed
);
133 printf("nsPluginNativeWindowGtk2: NPPVpluginNeedsXEmbed=%d\n", needXEmbed
);
137 CreateXEmbedWindow();
145 return NS_ERROR_FAILURE
;
147 // Make sure to resize and re-place the window if required.
148 // Need to reset "window" each time as nsObjectFrame::DidReflow sets it
149 // to the ancestor window.
150 if(GTK_IS_XTBIN(mSocketWidget
)) {
151 gtk_xtbin_resize(mSocketWidget
, width
, height
);
152 // Point the NPWindow structures window to the actual X window
153 window
= (nsPluginPort
*)GTK_XTBIN(mSocketWidget
)->xtwindow
;
157 window
= (nsPluginPort
*)gtk_socket_get_id(GTK_SOCKET(mSocketWidget
));
160 printf("nsPluginNativeWindowGtk2: call SetWindow with xid=%p\n", (void *)window
);
162 } // nsPluginWindowType_Window
163 aPluginInstance
->SetWindow(this);
165 else if (mPluginInstance
)
166 mPluginInstance
->SetWindow(nsnull
);
168 SetPluginInstance(aPluginInstance
);
172 nsresult
nsPluginNativeWindowGtk2::CreateXEmbedWindow() {
173 NS_ASSERTION(!mSocketWidget
,"Already created a socket widget!");
175 GdkWindow
*parent_win
= gdk_window_lookup((XID
)window
);
176 mSocketWidget
= gtk_socket_new();
178 //attach the socket to the container widget
179 gtk_widget_set_parent_window(mSocketWidget
, parent_win
);
181 // Make sure to handle the plug_removed signal. If we don't the
182 // socket will automatically be destroyed when the plug is
183 // removed, which means we're destroying it more than once.
185 g_signal_connect(mSocketWidget
, "plug_removed",
186 G_CALLBACK(plug_removed_cb
), NULL
);
188 g_signal_connect(mSocketWidget
, "destroy",
189 GTK_SIGNAL_FUNC(gtk_widget_destroyed
), &mSocketWidget
);
191 gpointer user_data
= NULL
;
192 gdk_window_get_user_data(parent_win
, &user_data
);
194 GtkContainer
*container
= GTK_CONTAINER(user_data
);
195 gtk_container_add(container
, mSocketWidget
);
196 gtk_widget_realize(mSocketWidget
);
198 // Resize before we show
201 gtk_widget_show(mSocketWidget
);
204 window
= (nsPluginPort
*)gtk_socket_get_id(GTK_SOCKET(mSocketWidget
));
206 // Fill out the ws_info structure.
207 // (The windowless case is done in nsObjectFrame.cpp.)
208 GdkWindow
*gdkWindow
= gdk_window_lookup((XID
)window
);
209 mWsInfo
.display
= GDK_WINDOW_XDISPLAY(gdkWindow
);
210 mWsInfo
.colormap
= GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(gdkWindow
));
211 GdkVisual
* gdkVisual
= gdk_drawable_get_visual(gdkWindow
);
212 mWsInfo
.visual
= GDK_VISUAL_XVISUAL(gdkVisual
);
213 mWsInfo
.depth
= gdkVisual
->depth
;
218 void nsPluginNativeWindowGtk2::SetAllocation() {
222 GtkAllocation new_allocation
;
223 new_allocation
.x
= 0;
224 new_allocation
.y
= 0;
225 new_allocation
.width
= width
;
226 new_allocation
.height
= height
;
227 gtk_widget_size_allocate(mSocketWidget
, &new_allocation
);
230 nsresult
nsPluginNativeWindowGtk2::CreateXtWindow() {
231 NS_ASSERTION(!mSocketWidget
,"Already created a socket widget!");
234 printf("About to create new xtbin of %i X %i from %p...\n",
235 width
, height
, (void*)window
);
237 GdkWindow
*gdkWindow
= gdk_window_lookup((XID
)window
);
238 mSocketWidget
= gtk_xtbin_new(gdkWindow
, 0);
239 // Check to see if creating the xtbin failed for some reason.
240 // if it did, we can't go any further.
242 return NS_ERROR_FAILURE
;
244 gtk_widget_set_size_request(mSocketWidget
, width
, height
);
247 printf("About to show xtbin(%p)...\n", (void*)mSocketWidget
); fflush(NULL
);
249 gtk_widget_show(mSocketWidget
);
251 printf("completed gtk_widget_show(%p)\n", (void*)mSocketWidget
); fflush(NULL
);
254 // Fill out the ws_info structure.
255 GtkXtBin
* xtbin
= GTK_XTBIN(mSocketWidget
);
256 // The xtbin has its own Display structure.
257 mWsInfo
.display
= xtbin
->xtdisplay
;
258 mWsInfo
.colormap
= xtbin
->xtclient
.xtcolormap
;
259 mWsInfo
.visual
= xtbin
->xtclient
.xtvisual
;
260 mWsInfo
.depth
= xtbin
->xtclient
.xtdepth
;
261 // Leave mWsInfo.type = 0 - Who knows what this is meant to be?
263 XFlush(mWsInfo
.display
);
268 PRBool
nsPluginNativeWindowGtk2::CanGetValueFromPlugin(nsCOMPtr
<nsIPluginInstance
> &aPluginInstance
)
271 if(aPluginInstance
) {
273 nsCOMPtr
<nsIPluginInstancePeer
> peer
;
275 rv
= aPluginInstance
->GetPeer(getter_AddRefs(peer
));
276 if (NS_SUCCEEDED(rv
) && peer
) {
277 const char *aMimeType
= nsnull
;
279 peer
->GetMIMEType((nsMIMEType
*)&aMimeType
);
281 (PL_strncasecmp(aMimeType
, "application/x-java-vm", 21) == 0 ||
282 PL_strncasecmp(aMimeType
, "application/x-java-applet", 25) == 0)) {
283 nsCOMPtr
<nsIPluginHost
> pluginHost
= do_GetService(kPluginManagerCID
, &rv
);
284 if (NS_SUCCEEDED(rv
) && pluginHost
) {
285 nsIPlugin
* pluginFactory
= NULL
;
287 rv
= pluginHost
->GetPluginFactory("application/x-java-vm", &pluginFactory
);
288 if (NS_SUCCEEDED(rv
) && pluginFactory
) {
289 const char * jpiDescription
= NULL
;
291 pluginFactory
->GetValue(nsPluginVariable_DescriptionString
, (void*)&jpiDescription
);
296 * "Java(TM) Plug-in" is Sun's Java Plugin Trademark,
297 * so we are sure that this is Sun 's Java Plugin if
298 * the description start with "Java(TM) Plug-in"
300 if (PL_strncasecmp(jpiDescription
, "Java(TM) Plug-in", 16) == 0) {
301 // Java Plugin support Xembed from JRE 1.5
302 if (PL_strcasecmp(jpiDescription
+ 17, "1.5") < 0)
305 if (PL_strncasecmp(jpiDescription
, "<a href=\"http://www.blackdown.org/java-linux.html\">", 51) == 0) {
306 // Java Plugin support Xembed from JRE 1.5
307 if (PL_strcasecmp(jpiDescription
+ 92, "1.5") < 0)
310 if (PL_strncasecmp(jpiDescription
, "IBM Java(TM) Plug-in", 20) == 0) {
311 // Java Plugin support Xembed from JRE 1.5
312 if (PL_strcasecmp(jpiDescription
+ 27, "1.5") < 0)
327 plug_removed_cb (GtkWidget
*widget
, gpointer data
)
329 // Gee, thanks for the info!