GtkPlug/GtkSocket workaround for Bonobo
- From: Maciej Stachowiak <mjs eazel com>
- To: gnome-components-list gnome org, gnomad-hackers eazel com
- Subject: GtkPlug/GtkSocket workaround for Bonobo
- Date: 25 Jan 2000 23:17:07 -0800
We really need the following change for Nautilus work. OK if I check
it in? I checked that Bonobo still works with it in both the in-proc
and out-of-proc control cases, and I am pretty sure the memory
management works out properly.
2000-01-25 Maciej Stachowiak <mjs@eazel.com>
* bonobo/bonobo-control.c, bonobo/bonobo-control-frame.c: Detect
when the control is in the same process as the frame; in that
case, reduce to a simple containement relationship instead of
using GtkPlug/GtkSocket, to avoid bugs in GtkPlug/GtkSocket in the
same-application case.
Index: bonobo/bonobo-control-frame.c
===================================================================
RCS file: /cvs/gnome/bonobo/bonobo/bonobo-control-frame.c,v
retrieving revision 1.8
diff -u -r1.8 bonobo-control-frame.c
--- bonobo/bonobo-control-frame.c 2000/01/24 23:43:10 1.8
+++ bonobo/bonobo-control-frame.c 2000/01/25 09:19:09
@@ -12,6 +12,7 @@
#include <gtk/gtksignal.h>
#include <gtk/gtkmarshal.h>
#include <gtk/gtkplug.h>
+#include <gtk/gtkframe.h>
#include <bonobo/gnome-main.h>
#include <bonobo/gnome-control.h>
#include <bonobo/gnome-control-frame.h>
@@ -37,6 +38,7 @@
struct _GnomeControlFramePrivate {
GNOME_Control control;
+ GtkWidget *control;
GtkWidget *socket;
GnomeUIHandler *uih;
GnomePropertyBag *propbag;
@@ -198,9 +200,21 @@
gtk_widget_show (control_frame->priv->socket);
/*
- * When the socket is realized, we pass its Window ID to our
- * Control.
+ * Finally, create a frame to hold the socket; this no-window
+ * container is needed solely for the sake of bypassing
+ * plug/socket in the local case.
*/
+ control_frame->priv->container = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type ( GTK_FRAME (control_frame->priv->container), GTK_SHADOW_NONE);
+ gtk_container_set_border_width (GTK_CONTAINER (control_frame->priv->container), 0);
+ gtk_container_add (GTK_CONTAINER (control_frame->priv->container),
+ control_frame->priv->socket);
+ gtk_widget_show (control_frame->priv->container);
+
+
+ /*
+ * When the socket is realized, we pass its Window ID to our
+ * Control. */
gtk_signal_connect (GTK_OBJECT (control_frame->priv->socket),
"realize",
GTK_SIGNAL_FUNC (gnome_control_frame_set_remote_window),
@@ -525,7 +539,7 @@
g_return_val_if_fail (control_frame != NULL, NULL);
g_return_val_if_fail (GNOME_IS_CONTROL_FRAME (control_frame), NULL);
- return control_frame->priv->socket;
+ return control_frame->priv->container;
}
/**
Index: bonobo/bonobo-control.c
===================================================================
RCS file: /cvs/gnome/bonobo/bonobo/bonobo-control.c,v
retrieving revision 1.12
diff -u -r1.12 bonobo-control.c
--- bonobo/bonobo-control.c 2000/01/25 07:22:50 1.12
+++ bonobo/bonobo-control.c 2000/01/25 09:19:09
@@ -35,6 +35,7 @@
GtkWidget *plug;
int plug_destroy_id;
+ gboolean is_local;
GtkWidget *widget;
@@ -156,25 +157,56 @@
gnome_control_set_control_frame (control, frame);
}
+
+
+GtkWidget *bonobo_gtk_widget_from_x11_id(guint32 xid)
+{
+ GdkWindow *window;
+ gpointer data;
+
+ window = gdk_window_lookup (xid);
+
+ if (!window) {
+ return NULL;
+ }
+
+ gdk_window_get_user_data(window, &data);
+
+ if (!data || !GTK_IS_WIDGET(data)) {
+ return NULL;
+ } else {
+ return GTK_WIDGET(data);
+ }
+}
+
static void
impl_GNOME_Control_set_window (PortableServer_Servant servant,
GNOME_Control_windowid id,
CORBA_Environment *ev)
{
guint32 x11_id;
+ GtkWidget *local_socket;
GnomeControl *control = GNOME_CONTROL (gnome_object_from_servant (servant));
x11_id = window_id_demangle (id);
- control->priv->plug = gtk_plug_new (x11_id);
- control->priv->plug_destroy_id = gtk_signal_connect (
- GTK_OBJECT (control->priv->plug), "destroy_event",
- GTK_SIGNAL_FUNC (gnome_control_plug_destroy_cb), control);
+ local_socket = bonobo_gtk_widget_from_x11_id(x11_id);
-
- gtk_container_add (GTK_CONTAINER (control->priv->plug), control->priv->widget);
-
- gtk_widget_show_all (control->priv->plug);
+ if (local_socket) {
+ GtkWidget *socket_parent;
+ control->priv->is_local = TRUE;
+ socket_parent = local_socket->parent;
+ gtk_container_remove (GTK_CONTAINER (socket_parent), local_socket);
+ gtk_container_add (GTK_CONTAINER (socket_parent), control->priv->widget);
+ gtk_widget_show_all (control->priv->widget);
+ } else {
+ control->priv->plug = gtk_plug_new (x11_id);
+ control->priv->plug_destroy_id = gtk_signal_connect (
+ GTK_OBJECT (control->priv->plug), "destroy_event",
+ GTK_SIGNAL_FUNC (gnome_control_plug_destroy_cb), control);
+ gtk_container_add (GTK_CONTAINER (control->priv->plug), control->priv->widget);
+ gtk_widget_show_all (control->priv->plug);
+ }
}
static void
@@ -187,7 +219,8 @@
* Nothing.
*
* In the Gnome implementation of Bonobo, all size negotiation
- * is handled by GtkPlug/GtkSocket for us.
+ * is handled by GtkPlug/GtkSocket for us, or GtkFrame in the
+ * local case.
*/
}
@@ -327,11 +360,14 @@
/*
* If the plug still exists, destroy it. The plug might not
* exist in the case where the container application died,
- * taking the plug out with it. In that case,
- * plug_destroy_cb() would have been invoked, and it would
- * have triggered the destruction of the Control. Which is why
- * we're here now.
+ * taking the plug out with it, or the optimized local case
+ * where the plug/socket mechanism was bypassed. In the
+ * formaer case, plug_destroy_cb() would have been invoked,
+ * and it would have triggered the destruction of the Control,
+ * which is why we're here now. In the latter case, it's not
+ * needed because there is no plug.
*/
+
if (control->priv->plug) {
gtk_signal_disconnect (GTK_OBJECT (control->priv->plug), control->priv->plug_destroy_id);
gtk_object_destroy (GTK_OBJECT (control->priv->plug));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]