1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
diff --git a/dom/plugins/base/nsPluginNativeWindowGtk.cpp b/dom/plugins/base/nsPluginNativeWindowGtk.cpp
--- a/dom/plugins/base/nsPluginNativeWindowGtk.cpp
+++ b/dom/plugins/base/nsPluginNativeWindowGtk.cpp
@@ -19,16 +19,17 @@
#if (GTK_MAJOR_VERSION == 3)
#include <gtk/gtkx.h>
#else
#include "gtk2xtbin.h"
#endif
#include "mozilla/X11Util.h"
+static void plug_added_cb(GtkWidget *widget, gpointer data);
static gboolean plug_removed_cb (GtkWidget *widget, gpointer data);
static void socket_unrealize_cb (GtkWidget *widget, gpointer data);
nsPluginNativeWindowGtk::nsPluginNativeWindowGtk() : nsPluginNativeWindow()
{
// initialize the struct fields
window = nullptr;
x = 0;
@@ -158,16 +159,19 @@ nsresult nsPluginNativeWindowGtk::Create
//attach the socket to the container widget
gtk_widget_set_parent_window(mSocketWidget, parent_win);
// enable/disable focus event handlers,
// see plugin_window_filter_func() for details
g_object_set_data(G_OBJECT(mSocketWidget), "enable-xt-focus", (void *)aEnableXtFocus);
+ g_signal_connect(mSocketWidget, "plug_added",
+ G_CALLBACK(plug_added_cb), nullptr);
+
// Make sure to handle the plug_removed signal. If we don't the
// socket will automatically be destroyed when the plug is
// removed, which means we're destroying it more than once.
// SYNTAX ERROR.
g_signal_connect(mSocketWidget, "plug_removed",
G_CALLBACK(plug_removed_cb), nullptr);
g_signal_connect(mSocketWidget, "unrealize",
@@ -273,16 +277,42 @@ nsresult nsPluginNativeWindowGtk::Create
// Leave mWsInfo.type = 0 - Who knows what this is meant to be?
XFlush(mWsInfo.display);
return NS_OK;
}
#endif
+static void
+plug_window_finalize_cb(gpointer socket, GObject* plug_window)
+{
+ g_object_unref(socket);
+}
+
+static void
+plug_added_cb(GtkWidget *socket, gpointer data)
+{
+ // The plug window has been embedded, and gtk_socket_add_window() has added
+ // a filter to the socket's plug_window, passing the socket as data for the
+ // filter, so the socket must live as long as events may be received on the
+ // plug window.
+ //
+ // https://git.gnome.org/browse/gtk+/tree/gtk/gtksocket.c?h=3.18.7#n1124
+ g_object_ref(socket);
+ // When the socket is unrealized, perhaps during gtk_widget_destroy() from
+ // ~nsPluginNativeWindowGtk, the plug is removed. The plug in the child
+ // process then destroys its widget and window. When the browser process
+ // receives the DestroyNotify event for the plug window, GDK releases its
+ // reference to plugWindow. This is typically the last reference and so the
+ // weak ref callback triggers release of the socket.
+ GdkWindow* plugWindow = gtk_socket_get_plug_window(GTK_SOCKET(socket));
+ g_object_weak_ref(G_OBJECT(plugWindow), plug_window_finalize_cb, socket);
+}
+
/* static */
gboolean
plug_removed_cb (GtkWidget *widget, gpointer data)
{
// Gee, thanks for the info!
return TRUE;
}
diff --git a/widget/gtk/mozgtk/mozgtk.c b/widget/gtk/mozgtk/mozgtk.c
--- a/widget/gtk/mozgtk/mozgtk.c
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -384,16 +384,17 @@ STUB(gtk_selection_data_targets_include_
STUB(gtk_separator_get_type)
STUB(gtk_separator_menu_item_new)
STUB(gtk_separator_tool_item_new)
STUB(gtk_settings_get_default)
STUB(gtk_settings_get_for_screen)
STUB(gtk_socket_add_id)
STUB(gtk_socket_get_id)
STUB(gtk_socket_get_type)
+STUB(gtk_socket_get_plug_window)
STUB(gtk_socket_new)
STUB(gtk_spin_button_new)
STUB(gtk_statusbar_new)
STUB(gtk_style_lookup_icon_set)
STUB(gtk_table_attach)
STUB(gtk_table_get_type)
STUB(gtk_table_new)
STUB(gtk_target_list_add)
|