[Fwd: Reparenting problem in the GnomeDock.]






Hi Ettore,

    As you know, I've been working on the reparenting problems in
Bonobo controls lately.  Federico helped me for a few hours today, and
we managed to track down the wacky issues we were seeing last night.

    The situation was this; on the component side, I was creating a
GtkLabel, wrapping it in a BonoboControl, and then passing that up to
the container.  The container was creating a new GnomeDockItem and
stuffing the Control into the DockItem.

    When the dock gets dragged out of the application, all of its
windows need to get reparented into the new floating window.  This
causes the container-side GtkSocket which is embedding the
BonoboControl to get re-realized.  When the GtkSocket is re-realized,
Bonobo transmits the new socket XID to the control via CORBA[1].  The
BonoboControl then creates a new plug using the new XID and reparents
the Control's top-level widget (in this case, the GtkLabel) into the
new plug.  The old plug is discarded.

    This is how things are supposed to work.  For some reason, though,
the plug was getting an X Delete event before the new XID arrived.
This caused the old plug to be destroyed, and made it impossible to
reparent the GtkLabel[2].

    So Federico and I tracked down why the plug was getting the delete
event.  It turns out that when you reparent a GnomeDockItem, you do
this (gnome-dock.c, line 910 or so, in drag_floating):

          gtk_container_remove (GTK_CONTAINER (item_widget->parent),
                                item_widget);
          gtk_widget_set_parent (item_widget, dock_widget);

The gtk_container_remove maps to gtk_bin_remove (since GnomeDockItem
subclasses GtkBin), which invokes gtk_window_unparent.  Which brings
us to this little piece of code (gtkwidget.c, line 1363 or so):

if (GTK_WIDGET_REALIZED (widget) && !GTK_WIDGET_IN_REPARENT (widget))
  gtk_widget_unrealize (widget);

So my plug was getting unrealized, which explains the X Delete event
the control was getting.  When I set the GTK_IN_REPARENT private
widget flag in gnome-dock.c, it worked perfectly, since
gtk_widget_unparent knew that we were in the process of reparenting a
window, and that it would therefore be a bad idea to unrealize the
window.

    So GnomeDock needs to be fixed.  I don't know what the correct
solution is, but here's my patch (the one that sets the private flag).

Nat

[1] One problem with the Bonobo code was that we were sending along
    the new XID without XSync'ing the server; this was unrelated to
    the reparenting problems, but is a pretty important lesson.
    Apparently XIDs can get allocated on the client side without any
    communication with the server, and so the XID which gets
    transmitted to the control may be completely unknown to the X
    server.

[2] I don't know why it was impossible.  I tried doing stuff like:
	gtk_object_ref (GTK_OBJECT (control->priv->widget));
	gtk_widget_unparent (control->priv->widget);
	gtk_object_unref (GTK_OBJECT (control->priv->widget));
	gtk_container_add (GTK_CONTAINER (control->priv->plug),
                           control->priv->widget);

    where control->priv->widget is the GtkLabel, but this failed
    pretty horribly, and I never found out why.



diff -u -r1.28 gnome-dock.c
--- gnome-dock.c	1999/10/03 10:39:33	1.28
+++ gnome-dock.c	2000/02/16 03:08:48
@@ -21,6 +21,7 @@
 */
 
 #include <gtk/gtk.h>
+#include <gtk/gtkprivate.h>
 
 #include "gnome-dock.h"
 #include "gnome-dock-band.h"
@@ -904,10 +905,15 @@
         {
           gtk_widget_ref (item_widget);
 
+	  GTK_PRIVATE_SET_FLAG (item_widget, GTK_IN_REPARENT);
+
           gtk_container_remove (GTK_CONTAINER (item_widget->parent),
                                 item_widget);
           gtk_widget_set_parent (item_widget, dock_widget);
 
+	  GTK_PRIVATE_UNSET_FLAG (item_widget, GTK_IN_REPARENT);
+
+
           dock->floating_children = g_list_prepend (dock->floating_children,
                                                     item);
 





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]