]> Pileus Git - ~andy/gtk/commitdiff
For XEMBED embedding add a _XEMBED_INFO property to the client with
authorOwen Taylor <otaylor@redhat.com>
Tue, 3 Jul 2001 14:14:30 +0000 (14:14 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Tue, 3 Jul 2001 14:14:30 +0000 (14:14 +0000)
Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>

* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
XEMBED embedding add a _XEMBED_INFO property to the
client with version number and a "mapped" flags.
Use the mapped flag instead of the racy MapRequestEvent

        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
code to reliably set things (when the child is a passive
embedder participating in the XEMBED protocol) intead
of just being a hack for embedding non-participating
programs. Fix various bugs and race conditions.

* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
work by simply making the GtkSocket the gtk parent
of the GtkPlug. Set a flag in this case and make
the GtkPlug work like a normal container by overriding
methods such as check_resize and "chaining past" GtkWindow
to GtkBin.

  * gtk/gtkentry.c (gtk_entry_real_activate)
  gtk/gtkmain.c (gtk_propagate_event):
  Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).

* gtk/gtkwidget.c (gtk_widget_get_toplevel,
gtk_widget_get_ancestor):
Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
might not give the expected result and recommend
an alternative.

* tests/testsocket.c tests/testsocket_child.c
tests/testsocket_common.c tests/Makefile.am: Extended
to test different type of adding plugs to sockets
(local,active,passive), and to test mapping/unmapping
the plug.

  * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
  mark the window as destroyed until after we
  called _gdk_windowing_window_destroy().
(_gdk_windowing_window_destroy() may use GDK functions
on the window.)

  * gdk/x11/gdkinput.c: Remove the check for finalization -
  devices can be finalized under some circumnstances.

  * gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
  small problem with GDK_TYPE_DEVICE.

21 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/gdkwindow.c
gdk/x11/gdkinput-x11.c
gdk/x11/gdkinput.c
gtk/gtkentry.c
gtk/gtkmain.c
gtk/gtkplug.c
gtk/gtkplug.h
gtk/gtksocket.c
gtk/gtksocket.h
gtk/gtkwidget.c
gtk/xembed.h
tests/Makefile.am
tests/testsocket.c
tests/testsocket_child.c

index aadd7bd5b3f640ab7074a397f5dc9b27f5f3f79e..3f9308e8ddcd1398b9b8f3dcac95142cabc55508 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,51 @@
+Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
+       XEMBED embedding add a _XEMBED_INFO property to the
+       client with version number and a "mapped" flags.
+       Use the mapped flag instead of the racy MapRequestEvent
+
+        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
+       code to reliably set things (when the child is a passive
+       embedder participating in the XEMBED protocol) intead
+       of just being a hack for embedding non-participating
+       programs. Fix various bugs and race conditions.
+       
+       * gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
+       work by simply making the GtkSocket the gtk parent
+       of the GtkPlug. Set a flag in this case and make
+       the GtkPlug work like a normal container by overriding
+       methods such as check_resize and "chaining past" GtkWindow
+       to GtkBin.
+
+       * gtk/gtkentry.c (gtk_entry_real_activate)
+         gtk/gtkmain.c (gtk_propagate_event): 
+       Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
+       
+       * gtk/gtkwidget.c (gtk_widget_get_toplevel,
+       gtk_widget_get_ancestor):
+       Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
+       might not give the expected result and recommend
+       an alternative.
+
+       * tests/testsocket.c tests/testsocket_child.c
+       tests/testsocket_common.c tests/Makefile.am: Extended
+       to test different type of adding plugs to sockets
+       (local,active,passive), and to test mapping/unmapping
+       the plug.
+
+       * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
+       mark the window as destroyed until after we
+       called _gdk_windowing_window_destroy().
+       (_gdk_windowing_window_destroy() may use GDK functions
+       on the window.)
+
+       * gdk/x11/gdkinput.c: Remove the check for finalization - 
+       devices can be finalized under some circumnstances.
+       * gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix 
+       small problem with GDK_TYPE_DEVICE.
 2001-07-02  Havoc Pennington  <hp@pobox.com>
 
        * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to 
index aadd7bd5b3f640ab7074a397f5dc9b27f5f3f79e..3f9308e8ddcd1398b9b8f3dcac95142cabc55508 100644 (file)
@@ -1,3 +1,51 @@
+Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
+       XEMBED embedding add a _XEMBED_INFO property to the
+       client with version number and a "mapped" flags.
+       Use the mapped flag instead of the racy MapRequestEvent
+
+        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
+       code to reliably set things (when the child is a passive
+       embedder participating in the XEMBED protocol) intead
+       of just being a hack for embedding non-participating
+       programs. Fix various bugs and race conditions.
+       
+       * gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
+       work by simply making the GtkSocket the gtk parent
+       of the GtkPlug. Set a flag in this case and make
+       the GtkPlug work like a normal container by overriding
+       methods such as check_resize and "chaining past" GtkWindow
+       to GtkBin.
+
+       * gtk/gtkentry.c (gtk_entry_real_activate)
+         gtk/gtkmain.c (gtk_propagate_event): 
+       Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
+       
+       * gtk/gtkwidget.c (gtk_widget_get_toplevel,
+       gtk_widget_get_ancestor):
+       Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
+       might not give the expected result and recommend
+       an alternative.
+
+       * tests/testsocket.c tests/testsocket_child.c
+       tests/testsocket_common.c tests/Makefile.am: Extended
+       to test different type of adding plugs to sockets
+       (local,active,passive), and to test mapping/unmapping
+       the plug.
+
+       * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
+       mark the window as destroyed until after we
+       called _gdk_windowing_window_destroy().
+       (_gdk_windowing_window_destroy() may use GDK functions
+       on the window.)
+
+       * gdk/x11/gdkinput.c: Remove the check for finalization - 
+       devices can be finalized under some circumnstances.
+       * gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix 
+       small problem with GDK_TYPE_DEVICE.
 2001-07-02  Havoc Pennington  <hp@pobox.com>
 
        * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to 
index aadd7bd5b3f640ab7074a397f5dc9b27f5f3f79e..3f9308e8ddcd1398b9b8f3dcac95142cabc55508 100644 (file)
@@ -1,3 +1,51 @@
+Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
+       XEMBED embedding add a _XEMBED_INFO property to the
+       client with version number and a "mapped" flags.
+       Use the mapped flag instead of the racy MapRequestEvent
+
+        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
+       code to reliably set things (when the child is a passive
+       embedder participating in the XEMBED protocol) intead
+       of just being a hack for embedding non-participating
+       programs. Fix various bugs and race conditions.
+       
+       * gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
+       work by simply making the GtkSocket the gtk parent
+       of the GtkPlug. Set a flag in this case and make
+       the GtkPlug work like a normal container by overriding
+       methods such as check_resize and "chaining past" GtkWindow
+       to GtkBin.
+
+       * gtk/gtkentry.c (gtk_entry_real_activate)
+         gtk/gtkmain.c (gtk_propagate_event): 
+       Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
+       
+       * gtk/gtkwidget.c (gtk_widget_get_toplevel,
+       gtk_widget_get_ancestor):
+       Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
+       might not give the expected result and recommend
+       an alternative.
+
+       * tests/testsocket.c tests/testsocket_child.c
+       tests/testsocket_common.c tests/Makefile.am: Extended
+       to test different type of adding plugs to sockets
+       (local,active,passive), and to test mapping/unmapping
+       the plug.
+
+       * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
+       mark the window as destroyed until after we
+       called _gdk_windowing_window_destroy().
+       (_gdk_windowing_window_destroy() may use GDK functions
+       on the window.)
+
+       * gdk/x11/gdkinput.c: Remove the check for finalization - 
+       devices can be finalized under some circumnstances.
+       * gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix 
+       small problem with GDK_TYPE_DEVICE.
 2001-07-02  Havoc Pennington  <hp@pobox.com>
 
        * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to 
index aadd7bd5b3f640ab7074a397f5dc9b27f5f3f79e..3f9308e8ddcd1398b9b8f3dcac95142cabc55508 100644 (file)
@@ -1,3 +1,51 @@
+Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
+       XEMBED embedding add a _XEMBED_INFO property to the
+       client with version number and a "mapped" flags.
+       Use the mapped flag instead of the racy MapRequestEvent
+
+        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
+       code to reliably set things (when the child is a passive
+       embedder participating in the XEMBED protocol) intead
+       of just being a hack for embedding non-participating
+       programs. Fix various bugs and race conditions.
+       
+       * gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
+       work by simply making the GtkSocket the gtk parent
+       of the GtkPlug. Set a flag in this case and make
+       the GtkPlug work like a normal container by overriding
+       methods such as check_resize and "chaining past" GtkWindow
+       to GtkBin.
+
+       * gtk/gtkentry.c (gtk_entry_real_activate)
+         gtk/gtkmain.c (gtk_propagate_event): 
+       Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
+       
+       * gtk/gtkwidget.c (gtk_widget_get_toplevel,
+       gtk_widget_get_ancestor):
+       Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
+       might not give the expected result and recommend
+       an alternative.
+
+       * tests/testsocket.c tests/testsocket_child.c
+       tests/testsocket_common.c tests/Makefile.am: Extended
+       to test different type of adding plugs to sockets
+       (local,active,passive), and to test mapping/unmapping
+       the plug.
+
+       * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
+       mark the window as destroyed until after we
+       called _gdk_windowing_window_destroy().
+       (_gdk_windowing_window_destroy() may use GDK functions
+       on the window.)
+
+       * gdk/x11/gdkinput.c: Remove the check for finalization - 
+       devices can be finalized under some circumnstances.
+       * gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix 
+       small problem with GDK_TYPE_DEVICE.
 2001-07-02  Havoc Pennington  <hp@pobox.com>
 
        * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to 
index aadd7bd5b3f640ab7074a397f5dc9b27f5f3f79e..3f9308e8ddcd1398b9b8f3dcac95142cabc55508 100644 (file)
@@ -1,3 +1,51 @@
+Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
+       XEMBED embedding add a _XEMBED_INFO property to the
+       client with version number and a "mapped" flags.
+       Use the mapped flag instead of the racy MapRequestEvent
+
+        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
+       code to reliably set things (when the child is a passive
+       embedder participating in the XEMBED protocol) intead
+       of just being a hack for embedding non-participating
+       programs. Fix various bugs and race conditions.
+       
+       * gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
+       work by simply making the GtkSocket the gtk parent
+       of the GtkPlug. Set a flag in this case and make
+       the GtkPlug work like a normal container by overriding
+       methods such as check_resize and "chaining past" GtkWindow
+       to GtkBin.
+
+       * gtk/gtkentry.c (gtk_entry_real_activate)
+         gtk/gtkmain.c (gtk_propagate_event): 
+       Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
+       
+       * gtk/gtkwidget.c (gtk_widget_get_toplevel,
+       gtk_widget_get_ancestor):
+       Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
+       might not give the expected result and recommend
+       an alternative.
+
+       * tests/testsocket.c tests/testsocket_child.c
+       tests/testsocket_common.c tests/Makefile.am: Extended
+       to test different type of adding plugs to sockets
+       (local,active,passive), and to test mapping/unmapping
+       the plug.
+
+       * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
+       mark the window as destroyed until after we
+       called _gdk_windowing_window_destroy().
+       (_gdk_windowing_window_destroy() may use GDK functions
+       on the window.)
+
+       * gdk/x11/gdkinput.c: Remove the check for finalization - 
+       devices can be finalized under some circumnstances.
+       * gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix 
+       small problem with GDK_TYPE_DEVICE.
 2001-07-02  Havoc Pennington  <hp@pobox.com>
 
        * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to 
index aadd7bd5b3f640ab7074a397f5dc9b27f5f3f79e..3f9308e8ddcd1398b9b8f3dcac95142cabc55508 100644 (file)
@@ -1,3 +1,51 @@
+Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
+       XEMBED embedding add a _XEMBED_INFO property to the
+       client with version number and a "mapped" flags.
+       Use the mapped flag instead of the racy MapRequestEvent
+
+        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
+       code to reliably set things (when the child is a passive
+       embedder participating in the XEMBED protocol) intead
+       of just being a hack for embedding non-participating
+       programs. Fix various bugs and race conditions.
+       
+       * gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
+       work by simply making the GtkSocket the gtk parent
+       of the GtkPlug. Set a flag in this case and make
+       the GtkPlug work like a normal container by overriding
+       methods such as check_resize and "chaining past" GtkWindow
+       to GtkBin.
+
+       * gtk/gtkentry.c (gtk_entry_real_activate)
+         gtk/gtkmain.c (gtk_propagate_event): 
+       Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
+       
+       * gtk/gtkwidget.c (gtk_widget_get_toplevel,
+       gtk_widget_get_ancestor):
+       Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
+       might not give the expected result and recommend
+       an alternative.
+
+       * tests/testsocket.c tests/testsocket_child.c
+       tests/testsocket_common.c tests/Makefile.am: Extended
+       to test different type of adding plugs to sockets
+       (local,active,passive), and to test mapping/unmapping
+       the plug.
+
+       * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
+       mark the window as destroyed until after we
+       called _gdk_windowing_window_destroy().
+       (_gdk_windowing_window_destroy() may use GDK functions
+       on the window.)
+
+       * gdk/x11/gdkinput.c: Remove the check for finalization - 
+       devices can be finalized under some circumnstances.
+       * gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix 
+       small problem with GDK_TYPE_DEVICE.
 2001-07-02  Havoc Pennington  <hp@pobox.com>
 
        * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to 
index aadd7bd5b3f640ab7074a397f5dc9b27f5f3f79e..3f9308e8ddcd1398b9b8f3dcac95142cabc55508 100644 (file)
@@ -1,3 +1,51 @@
+Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
+       XEMBED embedding add a _XEMBED_INFO property to the
+       client with version number and a "mapped" flags.
+       Use the mapped flag instead of the racy MapRequestEvent
+
+        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
+       code to reliably set things (when the child is a passive
+       embedder participating in the XEMBED protocol) intead
+       of just being a hack for embedding non-participating
+       programs. Fix various bugs and race conditions.
+       
+       * gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
+       work by simply making the GtkSocket the gtk parent
+       of the GtkPlug. Set a flag in this case and make
+       the GtkPlug work like a normal container by overriding
+       methods such as check_resize and "chaining past" GtkWindow
+       to GtkBin.
+
+       * gtk/gtkentry.c (gtk_entry_real_activate)
+         gtk/gtkmain.c (gtk_propagate_event): 
+       Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
+       
+       * gtk/gtkwidget.c (gtk_widget_get_toplevel,
+       gtk_widget_get_ancestor):
+       Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
+       might not give the expected result and recommend
+       an alternative.
+
+       * tests/testsocket.c tests/testsocket_child.c
+       tests/testsocket_common.c tests/Makefile.am: Extended
+       to test different type of adding plugs to sockets
+       (local,active,passive), and to test mapping/unmapping
+       the plug.
+
+       * gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
+       mark the window as destroyed until after we
+       called _gdk_windowing_window_destroy().
+       (_gdk_windowing_window_destroy() may use GDK functions
+       on the window.)
+
+       * gdk/x11/gdkinput.c: Remove the check for finalization - 
+       devices can be finalized under some circumnstances.
+       * gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix 
+       small problem with GDK_TYPE_DEVICE.
 2001-07-02  Havoc Pennington  <hp@pobox.com>
 
        * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to 
index 94d2a394677fc66c8367f1dea423d60aa0e1c64c..81c919bab1b6316abc52944bb27b523451fa5670 100644 (file)
@@ -293,7 +293,6 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
       if (!GDK_WINDOW_DESTROYED (window))
        {
          private->state |= GDK_WINDOW_STATE_WITHDRAWN;
-         private->destroyed = TRUE;
          
          if (private->parent)
            {
@@ -332,6 +331,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
            }
          
          _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+         private->destroyed = TRUE;
 
          if (private->filters)
            {
index 1dd32e4a370870179d946ba5ff98c2352be8fe19..dfdae3d9495534329bfe0e2729ef566b37db3622 100644 (file)
@@ -96,7 +96,7 @@ gdk_input_device_new (XDeviceInfo *device, gint include_core)
   XAnyClassPtr class;
   gint i,j;
 
-  gdkdev = g_object_new (GDK_TYPE_DEVICE_PRIVATE, 1);
+  gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
 
   gdkdev->deviceid = device->id;
   if (device->name[0])
index 2232f584d4b4ac885aff766486347cf978f92fad..7e952c4492f39d05340c28c12532d746f53a07c1 100644 (file)
@@ -66,18 +66,6 @@ _gdk_init_input_core (void)
   gdk_core_pointer->keys = NULL;
 }
 
-static void
-gdk_device_finalize (GObject *object)
-{
-  g_error ("A GdkDevice object was finalized. This should not happen");
-}
-
-static void
-gdk_device_class_init (GObjectClass *class)
-{
-  class->finalize = gdk_device_finalize;
-}
-
 GType
 gdk_device_get_type (void)
 {
@@ -90,7 +78,7 @@ gdk_device_get_type (void)
         sizeof (GdkDeviceClass),
         (GBaseInitFunc) NULL,
         (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) gdk_device_class_init,
+        (GClassInitFunc) NULL,
         NULL,           /* class_finalize */
         NULL,           /* class_data */
         sizeof (GdkDevicePrivate),
index 9eb7fc1280e98efef6becc0764ea466d44c3a526..58c910c9610867f2cae32b2497f243016d00a2b7 100644 (file)
@@ -2022,17 +2022,21 @@ static void
 gtk_entry_real_activate (GtkEntry *entry)
 {
   GtkWindow *window;
+  GtkWidget *toplevel;
   GtkWidget *widget;
 
   widget = GTK_WIDGET (entry);
 
   if (entry->activates_default)
     {
-      window = (GtkWindow *) gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+      toplevel = gtk_widget_get_toplevel (widget);
+      if (toplevel && GTK_IS_WINDOW (toplevel))
+       {
+         window = GTK_WINDOW (toplevel);
       
-      if (window &&
-          window->default_widget != widget)
-        gtk_window_activate_default (window);
+         if (window && window->default_widget != widget)
+           gtk_window_activate_default (window);
+       }
     }
 }
 
index 6c7bcd3a1f0dadb2542a562e6e0b09c7d907a8b0..a8a6928041791a9dd827990bf9d5153a79728782 100644 (file)
@@ -1627,9 +1627,8 @@ gtk_propagate_event (GtkWidget *widget,
        */
       GtkWidget *window;
 
-      window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
-
-      if (window)
+      window = gtk_widget_get_toplevel (widget);
+      if (window && GTK_IS_WINDOW (window))
        {
          /* If there is a grab within the window, give the grab widget
           * a first crack at the key event
@@ -1639,8 +1638,8 @@ gtk_propagate_event (GtkWidget *widget,
          
          if (!handled_event)
            {
-             window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
-             if (window)
+             window = gtk_widget_get_toplevel (widget);
+             if (window && GTK_IS_WINDOW (window))
                {
                  if (GTK_WIDGET_IS_SENSITIVE (window))
                    gtk_widget_event (window, event);
index fa2b37c9f2e61e6fbc23270fa50e0144fa3fc786..03d7e22f069ef4650a234144740eb6b4f6bd0df3 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "gtkmain.h"
 #include "gtkplug.h"
+#include "gtkprivate.h"
 
 #include "gdk/gdkkeysyms.h"
 #include "x11/gdkx.h"
@@ -37,6 +38,12 @@ static void            gtk_plug_class_init            (GtkPlugClass     *klass);
 static void            gtk_plug_init                  (GtkPlug          *plug);
 static void            gtk_plug_realize               (GtkWidget        *widget);
 static void            gtk_plug_unrealize             (GtkWidget        *widget);
+static void            gtk_plug_show                  (GtkWidget        *widget);
+static void            gtk_plug_hide                  (GtkWidget        *widget);
+static void            gtk_plug_map                   (GtkWidget        *widget);
+static void            gtk_plug_unmap                 (GtkWidget        *widget);
+static void            gtk_plug_size_allocate         (GtkWidget        *widget,
+                                                      GtkAllocation    *allocation);
 static gboolean        gtk_plug_key_press_event       (GtkWidget        *widget,
                                                       GdkEventKey      *event);
 static void            gtk_plug_forward_key_press     (GtkPlug          *plug,
@@ -45,24 +52,28 @@ static void            gtk_plug_set_focus             (GtkWindow        *window,
                                                       GtkWidget        *focus);
 static gboolean        gtk_plug_focus                 (GtkWidget        *widget,
                                                       GtkDirectionType  direction);
+static void            gtk_plug_check_resize          (GtkContainer     *container);
 static void            gtk_plug_accel_entries_changed (GtkWindow        *window);
 static GdkFilterReturn gtk_plug_filter_func           (GdkXEvent        *gdk_xevent,
                                                       GdkEvent         *event,
                                                       gpointer          data);
 
-static void gtk_plug_free_grabbed_keys (GHashTable *key_table);
-static void handle_modality_off        (GtkPlug    *plug);
-static void send_xembed_message        (GtkPlug    *plug,
-                                       glong       message,
-                                       glong       detail,
-                                       glong       data1,
-                                       glong       data2,
-                                       guint32     time);
+static void gtk_plug_free_grabbed_keys (GHashTable    *key_table);
+static void handle_modality_off        (GtkPlug       *plug);
+static void send_xembed_message        (GtkPlug       *plug,
+                                       glong          message,
+                                       glong          detail,
+                                       glong          data1,
+                                       glong          data2,
+                                       guint32        time);
+static void xembed_set_info            (GdkWindow     *window,
+                                       unsigned long  flags);
 
 /* From Tk */
 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
   
 static GtkWindowClass *parent_class = NULL;
+static GtkBinClass *bin_class = NULL;
 
 GtkType
 gtk_plug_get_type ()
@@ -95,14 +106,24 @@ gtk_plug_class_init (GtkPlugClass *class)
 {
   GtkWidgetClass *widget_class = (GtkWidgetClass *)class;
   GtkWindowClass *window_class = (GtkWindowClass *)class;
+  GtkContainerClass *container_class = (GtkContainerClass *)class;
 
   parent_class = gtk_type_class (GTK_TYPE_WINDOW);
+  bin_class = gtk_type_class (GTK_TYPE_BIN);
 
   widget_class->realize = gtk_plug_realize;
   widget_class->unrealize = gtk_plug_unrealize;
   widget_class->key_press_event = gtk_plug_key_press_event;
 
- widget_class->focus = gtk_plug_focus;
+  widget_class->show = gtk_plug_show;
+  widget_class->hide = gtk_plug_hide;
+  widget_class->map = gtk_plug_map;
+  widget_class->unmap = gtk_plug_unmap;
+  widget_class->size_allocate = gtk_plug_size_allocate;
+
+  widget_class->focus = gtk_plug_focus;
+
+  container_class->check_resize = gtk_plug_check_resize;
 
   window_class->set_focus = gtk_plug_set_focus;
 #if 0  
@@ -121,18 +142,79 @@ gtk_plug_init (GtkPlug *plug)
   window->auto_shrink = TRUE;
 }
 
+static void
+gtk_plug_set_is_child (GtkPlug  *plug,
+                      gboolean  is_child)
+{
+  if (is_child)
+    {
+      GTK_WIDGET_UNSET_FLAGS (plug, GTK_TOPLEVEL);
+      GTK_PRIVATE_UNSET_FLAG (plug, GTK_ANCHORED);
+      gtk_container_set_resize_mode (GTK_CONTAINER (plug), GTK_RESIZE_PARENT);
+    }
+}
+
+/**
+ * _gtk_plug_add_to_socket:
+ * @plug: a #GtkPlug
+ * @socket: a #GtkSocket
+ * 
+ * Add a plug to a socket within the same application.
+ **/
 void
-gtk_plug_construct (GtkPlug *plug, GdkNativeWindow socket_id)
+_gtk_plug_add_to_socket (GtkPlug   *plug,
+                        GtkSocket *socket)
+{
+  GtkWidget *widget = GTK_WIDGET (plug);
+  
+  g_return_if_fail (GTK_IS_PLUG (plug));
+  g_return_if_fail (GTK_IS_SOCKET (socket));
+  g_return_if_fail (GTK_WIDGET_REALIZED (socket));
+
+  gtk_plug_set_is_child (plug, TRUE);
+  plug->same_app = TRUE;
+  socket->plug_widget = widget;
+
+  gtk_widget_set_parent (widget, GTK_WIDGET (socket));
+
+  if (GTK_WIDGET_REALIZED (widget))
+    gdk_window_reparent (widget->window, plug->socket_window, 0, 0);
+  else
+    gtk_widget_realize (widget);
+
+  if (GTK_WIDGET_VISIBLE (socket) && GTK_WIDGET_VISIBLE (widget))
+    {
+      if (GTK_WIDGET_MAPPED (socket))
+       gtk_widget_map (widget);
+
+      gtk_widget_queue_resize (widget);
+    }
+}
+
+void
+gtk_plug_construct (GtkPlug         *plug,
+                   GdkNativeWindow  socket_id)
 {
   if (socket_id)
     {
+      gpointer user_data = NULL;
+
       plug->socket_window = gdk_window_lookup (socket_id);
-      plug->same_app = TRUE;
 
-      if (plug->socket_window == NULL)
+      if (plug->socket_window)
+       gdk_window_get_user_data (plug->socket_window, &user_data);
+      else
+       plug->socket_window = gdk_window_foreign_new (socket_id);
+
+      if (user_data)
        {
-         plug->socket_window = gdk_window_foreign_new (socket_id);
-         plug->same_app = FALSE;
+         if (GTK_IS_SOCKET (user_data))
+           _gtk_plug_add_to_socket (plug, user_data);
+         else
+           {
+             g_warning (G_STRLOC "Can't create GtkPlug as child of non-GtkSocket");
+             plug->socket_window = NULL;
+           }
        }
     }
 }
@@ -164,11 +246,14 @@ gtk_plug_unrealize (GtkWidget *widget)
       plug->socket_window = NULL;
     }
 
-  if (plug->modality_window)
-    handle_modality_off (plug);
+  if (!plug->same_app)
+    {
+      if (plug->modality_window)
+       handle_modality_off (plug);
 
-  gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug));
-  g_object_unref (plug->modality_group);
+      gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug));
+      g_object_unref (plug->modality_group);
+    }
   
   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
@@ -213,29 +298,132 @@ gtk_plug_realize (GtkWidget *widget)
   attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
   attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
 
-  gdk_error_trap_push ();
-  widget->window = gdk_window_new (plug->socket_window, 
-                                  &attributes, attributes_mask);
-  gdk_flush ();
-  if (gdk_error_trap_pop ()) /* Uh-oh */
+  if (GTK_WIDGET_TOPLEVEL (widget))
     {
       gdk_error_trap_push ();
-      gdk_window_destroy (widget->window);
+      widget->window = gdk_window_new (plug->socket_window, 
+                                      &attributes, attributes_mask);
       gdk_flush ();
-      gdk_error_trap_pop ();
-      widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
+      if (gdk_error_trap_pop ()) /* Uh-oh */
+       {
+         gdk_error_trap_push ();
+         gdk_window_destroy (widget->window);
+         gdk_flush ();
+         gdk_error_trap_pop ();
+         widget->window = gdk_window_new (NULL, &attributes, attributes_mask);
+       }
+
+      GDK_WINDOW_TYPE (widget->window) = GDK_WINDOW_TOPLEVEL;
+      gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget);
+
+      plug->modality_group = gtk_window_group_new ();
+      gtk_window_group_add_window (plug->modality_group, window);
+      
+      xembed_set_info (widget->window, 0);
     }
+  else
+    widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);      
   
-  GDK_WINDOW_TYPE (widget->window) = GDK_WINDOW_TOPLEVEL;
   gdk_window_set_user_data (widget->window, window);
 
   widget->style = gtk_style_attach (widget->style, widget->window);
   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+gtk_plug_show (GtkWidget *widget)
+{
+  if (GTK_WIDGET_TOPLEVEL (widget))
+    GTK_WIDGET_CLASS (parent_class)->show (widget);
+  else
+    GTK_WIDGET_CLASS (bin_class)->show (widget);
+}
+
+static void
+gtk_plug_hide (GtkWidget *widget)
+{
+  if (GTK_WIDGET_TOPLEVEL (widget))
+    GTK_WIDGET_CLASS (parent_class)->hide (widget);
+  else
+    GTK_WIDGET_CLASS (bin_class)->hide (widget);
+}
+
+/* From gdkinternals.h */
+void gdk_synthesize_window_state (GdkWindow     *window,
+                                  GdkWindowState unset_flags,
+                                  GdkWindowState set_flags);
+
+static void
+gtk_plug_map (GtkWidget *widget)
+{
+  if (GTK_WIDGET_TOPLEVEL (widget))
+    {
+      GtkBin *bin = GTK_BIN (widget);
+      
+      GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+      if (bin->child &&
+         GTK_WIDGET_VISIBLE (bin->child) &&
+         !GTK_WIDGET_MAPPED (bin->child))
+       gtk_widget_map (bin->child);
+
+      xembed_set_info (widget->window, XEMBED_MAPPED);
+      
+      gdk_synthesize_window_state (widget->window,
+                                  GDK_WINDOW_STATE_WITHDRAWN,
+                                  0);
+    }
+  else
+    GTK_WIDGET_CLASS (bin_class)->map (widget);
+}
+
+static void
+gtk_plug_unmap (GtkWidget *widget)
+{
+  if (GTK_WIDGET_TOPLEVEL (widget))
+    {
+      GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+      gdk_window_hide (widget->window);
+      xembed_set_info (widget->window, 0);
+      
+      gdk_synthesize_window_state (widget->window,
+                                  0,
+                                  GDK_WINDOW_STATE_WITHDRAWN);
+    }
+  else
+    GTK_WIDGET_CLASS (bin_class)->unmap (widget);
+}
 
-  gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget);
+static void
+gtk_plug_size_allocate (GtkWidget     *widget,
+                       GtkAllocation *allocation)
+{
+  if (GTK_WIDGET_TOPLEVEL (widget))
+    GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
+  else
+    {
+      GtkBin *bin = GTK_BIN (widget);
+
+      if (GTK_WIDGET_REALIZED (widget))
+       gdk_window_move_resize (widget->window,
+                               allocation->x, allocation->y,
+                               allocation->width, allocation->height);
 
-  plug->modality_group = gtk_window_group_new ();
-  gtk_window_group_add_window (plug->modality_group, window);
+      if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+       {
+         GtkAllocation child_allocation;
+         
+         child_allocation.x = child_allocation.y = GTK_CONTAINER (widget)->border_width;
+         child_allocation.width =
+           MAX (1, (gint)allocation->width - child_allocation.x * 2);
+         child_allocation.height =
+           MAX (1, (gint)allocation->height - child_allocation.y * 2);
+         
+         gtk_widget_size_allocate (bin->child, &child_allocation);
+       }
+      
+    }
 }
 
 static gboolean
@@ -518,6 +706,15 @@ gtk_plug_focus (GtkWidget        *widget,
   return FALSE;
 }
 
+static void
+gtk_plug_check_resize (GtkContainer *container)
+{
+  if (GTK_WIDGET_TOPLEVEL (container))
+    GTK_CONTAINER_CLASS (parent_class)->check_resize (container);
+  else
+    GTK_CONTAINER_CLASS (bin_class)->check_resize (container);
+}
+
 static void
 send_xembed_message (GtkPlug *plug,
                     glong      message,
@@ -592,6 +789,25 @@ handle_modality_off (GtkPlug *plug)
     }
 }
 
+static void
+xembed_set_info (GdkWindow     *gdk_window,
+                unsigned long  flags)
+{
+  Display *display = GDK_WINDOW_XDISPLAY (gdk_window);
+  Window window = GDK_WINDOW_XWINDOW (gdk_window);
+  unsigned long buffer[2];
+  
+  Atom xembed_info_atom = gdk_atom_intern ("_XEMBED_INFO", FALSE);
+
+  buffer[1] = 0;               /* Protocol version */
+  buffer[1] = flags;
+
+  XChangeProperty (display, window,
+                  xembed_info_atom, xembed_info_atom, 32,
+                  PropModeReplace,
+                  (unsigned char *)buffer, 2);
+}
+
 static void
 handle_xembed_message (GtkPlug   *plug,
                       glong      message,
index 37907574dab1dd193fdcef297e28dccf302db6fb..d3274c50b497a84d3c49d986b3464219d1af63a3 100644 (file)
@@ -28,6 +28,7 @@
 
 
 #include <gdk/gdk.h>
+#include <gtk/gtksocket.h>
 #include <gtk/gtkwindow.h>
 
 
@@ -55,7 +56,7 @@ struct _GtkPlug
   GdkWindow *socket_window;
   GtkWidget *modality_window;
   GtkWindowGroup *modality_group;
-  gboolean   same_app;
+  guint same_app : 1;
 };
 
 struct _GtkPlugClass
@@ -69,6 +70,9 @@ void       gtk_plug_construct (GtkPlug *plug, GdkNativeWindow socket_id);
 GtkWidget* gtk_plug_new       (GdkNativeWindow socket_id);
 
 
+void _gtk_plug_add_to_socket (GtkPlug   *plug,
+                             GtkSocket *socket);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index f28310bccc313eae60cc9f4862555fde3febff05..a8e76850b18ed072d63b5e1d4c7e5471b680d707 100644 (file)
@@ -28,6 +28,7 @@
 #include "gdk/gdkkeysyms.h"
 #include "gtkmain.h"
 #include "gtkwindow.h"
+#include "gtkplug.h"
 #include "gtksignal.h"
 #include "gtksocket.h"
 #include "gtkdnd.h"
 
 /* Forward declararations */
 
-static void            gtk_socket_class_init           (GtkSocketClass   *klass);
-static void            gtk_socket_init                 (GtkSocket        *socket);
-static void            gtk_socket_realize              (GtkWidget        *widget);
-static void            gtk_socket_unrealize            (GtkWidget        *widget);
-static void            gtk_socket_size_request         (GtkWidget        *widget,
-                                                       GtkRequisition   *requisition);
-static void            gtk_socket_size_allocate        (GtkWidget        *widget,
-                                                       GtkAllocation    *allocation);
-static void            gtk_socket_hierarchy_changed    (GtkWidget        *widget,
-                                                       GtkWidget        *old_toplevel);
-static void            gtk_socket_grab_notify          (GtkWidget        *widget,
-                                                       gboolean          was_grabbed);
-static gboolean        gtk_socket_key_press_event      (GtkWidget        *widget,
-                                                       GdkEventKey      *event);
-static gboolean        gtk_socket_focus_in_event       (GtkWidget        *widget,
-                                                       GdkEventFocus    *event);
-static void            gtk_socket_claim_focus          (GtkSocket        *socket);
-static gboolean        gtk_socket_focus_out_event      (GtkWidget        *widget,
-                                                       GdkEventFocus    *event);
-static void            gtk_socket_send_configure_event (GtkSocket        *socket);
-static gboolean        gtk_socket_focus                (GtkWidget        *widget,
-                                                       GtkDirectionType  direction);
-static GdkFilterReturn gtk_socket_filter_func          (GdkXEvent        *gdk_xevent,
-                                                       GdkEvent         *event,
-                                                       gpointer          data);
-
-static void send_xembed_message (GtkSocket *socket,
-                                glong      message,
-                                glong      detail,
-                                glong      data1,
-                                glong      data2,
-                                guint32    time);
+static void     gtk_socket_class_init           (GtkSocketClass   *klass);
+static void     gtk_socket_init                 (GtkSocket        *socket);
+static void     gtk_socket_realize              (GtkWidget        *widget);
+static void     gtk_socket_unrealize            (GtkWidget        *widget);
+static void     gtk_socket_size_request         (GtkWidget        *widget,
+                                                GtkRequisition   *requisition);
+static void     gtk_socket_size_allocate        (GtkWidget        *widget,
+                                                GtkAllocation    *allocation);
+static void     gtk_socket_hierarchy_changed    (GtkWidget        *widget,
+                                                GtkWidget        *old_toplevel);
+static void     gtk_socket_grab_notify          (GtkWidget        *widget,
+                                                gboolean          was_grabbed);
+static gboolean gtk_socket_key_press_event      (GtkWidget        *widget,
+                                                GdkEventKey      *event);
+static gboolean gtk_socket_focus_in_event       (GtkWidget        *widget,
+                                                GdkEventFocus    *event);
+static void     gtk_socket_claim_focus          (GtkSocket        *socket);
+static gboolean gtk_socket_focus_out_event      (GtkWidget        *widget,
+                                                GdkEventFocus    *event);
+static void     gtk_socket_send_configure_event (GtkSocket        *socket);
+static gboolean gtk_socket_focus                (GtkWidget        *widget,
+                                                GtkDirectionType  direction);
+static void     gtk_socket_remove               (GtkContainer     *container,
+                                                GtkWidget        *widget);
+static void     gtk_socket_forall               (GtkContainer     *container,
+                                                gboolean          include_internals,
+                                                GtkCallback       callback,
+                                                gpointer          callback_data);
+
+
+static void            gtk_socket_add_window  (GtkSocket       *socket,
+                                              GdkNativeWindow  xid,
+                                              gboolean         need_reparent);
+static GdkFilterReturn gtk_socket_filter_func (GdkXEvent       *gdk_xevent,
+                                              GdkEvent        *event,
+                                              gpointer         data);
+
+static void     send_xembed_message (GtkSocket     *socket,
+                                    glong          message,
+                                    glong          detail,
+                                    glong          data1,
+                                    glong          data2,
+                                    guint32        time);
+static gboolean xembed_get_info     (GdkWindow     *gdk_window,
+                                    unsigned long *version,
+                                    unsigned long *flags);
 
 /* From Tk */
 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
@@ -124,8 +139,10 @@ gtk_socket_class_init (GtkSocketClass *class)
   widget_class->key_press_event = gtk_socket_key_press_event;
   widget_class->focus_in_event = gtk_socket_focus_in_event;
   widget_class->focus_out_event = gtk_socket_focus_out_event;
-
   widget_class->focus = gtk_socket_focus;
+  
+  container_class->remove = gtk_socket_remove;
+  container_class->forall = gtk_socket_forall;
 }
 
 static void
@@ -137,7 +154,7 @@ gtk_socket_init (GtkSocket *socket)
   socket->current_height = 0;
   
   socket->plug_window = NULL;
-  socket->same_app = FALSE;
+  socket->plug_widget = NULL;
   socket->focus_in = FALSE;
   socket->have_size = FALSE;
   socket->need_map = FALSE;
@@ -156,57 +173,7 @@ gtk_socket_new (void)
 void           
 gtk_socket_steal (GtkSocket *socket, GdkNativeWindow id)
 {
-  GtkWidget *widget;
-  gpointer user_data = NULL;
-  
-  widget = GTK_WIDGET (socket);
-  
-  socket->plug_window = gdk_window_lookup (id);
-
-  gdk_error_trap_push ();
-
-  if (socket->plug_window)
-    gdk_window_get_user_data (socket->plug_window,
-                              &user_data);
-  
-  if (user_data)      
-    {
-      /*
-       GtkWidget *child_widget;
-
-       child_widget = GTK_WIDGET (socket->plug_window->user_data);
-      */
-
-      g_warning("Stealing from same app not yet implemented");
-      
-      socket->same_app = TRUE;
-    }
-  else
-    {
-      socket->plug_window = gdk_window_foreign_new (id);
-      if (!socket->plug_window) /* was deleted before we could get it */
-       {
-         gdk_error_trap_pop ();
-         return;
-       }
-       
-      socket->same_app = FALSE;
-      socket->have_size = FALSE;
-
-      XSelectInput (GDK_DISPLAY (),
-                   GDK_WINDOW_XWINDOW(socket->plug_window),
-                   StructureNotifyMask | PropertyChangeMask);
-
-      gtk_widget_queue_resize (widget);
-    }
-
-  gdk_window_hide (socket->plug_window);
-  gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
-
-  gdk_flush ();
-  gdk_error_trap_pop ();
-  
-  socket->need_map = TRUE;
+  gtk_socket_add_window (socket, id, TRUE);
 }
 
 static void
@@ -307,42 +274,57 @@ gtk_socket_size_request (GtkWidget      *widget,
   
   socket = GTK_SOCKET (widget);
 
-  if (!socket->have_size && socket->plug_window)
+  if (socket->plug_widget)
     {
-      XSizeHints hints;
-      long supplied;
-
-      gdk_error_trap_push ();
-      
-      if (XGetWMNormalHints (GDK_DISPLAY(),
-                            GDK_WINDOW_XWINDOW (socket->plug_window),
-                            &hints, &supplied))
+      gtk_widget_size_request (socket->plug_widget, requisition);
+    }
+  else
+    {
+      if (socket->is_mapped && !socket->have_size && socket->plug_window)
        {
-         /* This is obsolete, according the X docs, but many programs
-          * still use it */
-         if (hints.flags & (PSize | USSize))
-           {
-             socket->request_width = hints.width;
-             socket->request_height = hints.height;
-           }
-         else if (hints.flags & PMinSize)
-           {
-             socket->request_width = hints.min_width;
-             socket->request_height = hints.min_height;
-           }
-         else if (hints.flags & PBaseSize)
+         XSizeHints hints;
+         long supplied;
+         
+         gdk_error_trap_push ();
+         
+         if (XGetWMNormalHints (GDK_DISPLAY(),
+                                GDK_WINDOW_XWINDOW (socket->plug_window),
+                                &hints, &supplied))
            {
-             socket->request_width = hints.base_width;
-             socket->request_height = hints.base_height;
+             /* This is obsolete, according the X docs, but many programs
+              * still use it */
+             if (hints.flags & (PSize | USSize))
+               {
+                 socket->request_width = hints.width;
+                 socket->request_height = hints.height;
+               }
+             else if (hints.flags & PMinSize)
+               {
+                 socket->request_width = hints.min_width;
+                 socket->request_height = hints.min_height;
+               }
+             else if (hints.flags & PBaseSize)
+               {
+                 socket->request_width = hints.base_width;
+                 socket->request_height = hints.base_height;
+               }
            }
+         socket->have_size = TRUE;     /* don't check again? */
+         
+         gdk_error_trap_pop ();
        }
-      socket->have_size = TRUE;        /* don't check again? */
 
-      gdk_error_trap_pop ();
+      if (socket->is_mapped && socket->have_size)
+       {
+         requisition->width = MAX (socket->request_width, 1);
+         requisition->height = MAX (socket->request_height, 1);
+       }
+      else
+       {
+         requisition->width = 1;
+         requisition->height = 1;
+       }
     }
-
-  requisition->width = MAX (socket->request_width, 1);
-  requisition->height = MAX (socket->request_height, 1);
 }
 
 static void
@@ -364,7 +346,18 @@ gtk_socket_size_allocate (GtkWidget     *widget,
                              allocation->x, allocation->y,
                              allocation->width, allocation->height);
 
-      if (socket->plug_window)
+      if (socket->plug_widget)
+       {
+         GtkAllocation child_allocation;
+
+         child_allocation.x = 0;
+         child_allocation.y = 0;
+         child_allocation.width = allocation->width;
+         child_allocation.height = allocation->height;
+
+         gtk_widget_size_allocate (socket->plug_widget, &child_allocation);
+       }
+      else if (socket->plug_window)
        {
          gdk_error_trap_push ();
          
@@ -652,9 +645,9 @@ gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
 
 #if 0
   GtkWidget *toplevel;
-  toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+  toplevel = gtk_widget_get_toplevel (widget);
   
-  if (toplevel)
+  if (toplevel && GTK_IS_WINDOW (toplevel))
     {
       XSetInputFocus (GDK_DISPLAY (),
                      GDK_WINDOW_XWINDOW (toplevel->window),
@@ -711,6 +704,9 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
   
   socket = GTK_SOCKET (widget);
 
+  if (socket->plug_widget)
+    return gtk_widget_child_focus (socket->plug_widget, direction);
+
   if (!GTK_WIDGET_HAS_FOCUS (widget))
     {
       switch (direction)
@@ -799,6 +795,39 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
 #endif  
 }
 
+static void
+gtk_socket_remove (GtkContainer *container,
+                  GtkWidget    *child)
+{
+  GtkSocket *socket = GTK_SOCKET (container);
+  gboolean widget_was_visible;
+
+  g_return_if_fail (child == socket->plug_widget);
+
+  widget_was_visible = GTK_WIDGET_VISIBLE (child);
+  
+  gtk_widget_unparent (child);
+  socket->plug_widget = NULL;
+  
+  /* queue resize regardless of GTK_WIDGET_VISIBLE (container),
+   * since that's what is needed by toplevels, which derive from GtkBin.
+   */
+  if (widget_was_visible)
+    gtk_widget_queue_resize (GTK_WIDGET (container));
+}
+
+static void
+gtk_socket_forall (GtkContainer *container,
+                  gboolean      include_internals,
+                  GtkCallback   callback,
+                  gpointer      callback_data)
+{
+  GtkSocket *socket = GTK_SOCKET (container);
+
+  if (socket->plug_widget)
+    (* callback) (socket->plug_widget, callback_data);
+}
+
 static void
 gtk_socket_send_configure_event (GtkSocket *socket)
 {
@@ -830,30 +859,98 @@ gtk_socket_send_configure_event (GtkSocket *socket)
 }
 
 static void
-gtk_socket_add_window (GtkSocket *socket, GdkNativeWindow xid)
+gtk_socket_add_window (GtkSocket        *socket,
+                      GdkNativeWindow   xid,
+                      gboolean          need_reparent)
 {
+
+  GtkWidget *widget = GTK_WIDGET (socket);
+  gpointer user_data = NULL;
+  
   socket->plug_window = gdk_window_lookup (xid);
-  socket->same_app = TRUE;
 
-  if (!socket->plug_window)
+  if (socket->plug_window)
+    {
+      g_object_ref (socket->plug_window);
+      gdk_window_get_user_data (socket->plug_window, &user_data);
+    }
+
+  if (user_data)               /* A widget's window in this process */
+    {
+      GtkWidget *child_widget = user_data;
+
+      if (!GTK_IS_PLUG (child_widget))
+       {
+         g_warning (G_STRLOC "Can't add non-GtkPlug to GtkSocket");
+         socket->plug_window = NULL;
+         gdk_error_trap_pop ();
+         
+         return;
+       }
+
+      _gtk_plug_add_to_socket (GTK_PLUG (child_widget), socket);
+    }
+  else                         /* A foreign window */
     {
       GtkWidget *toplevel;
       GdkDragProtocol protocol;
-      
-      socket->plug_window = gdk_window_foreign_new (xid);
-      if (!socket->plug_window) /* Already gone */
-       return;
-       
-      socket->same_app = FALSE;
+      unsigned long version;
+      unsigned long flags;
 
       gdk_error_trap_push ();
+
+      if (!socket->plug_window)
+       {  
+         socket->plug_window = gdk_window_foreign_new (xid);
+         if (!socket->plug_window) /* was deleted before we could get it */
+           {
+             gdk_error_trap_pop ();
+             return;
+           }
+       }
+       
       XSelectInput (GDK_DISPLAY (),
                    GDK_WINDOW_XWINDOW(socket->plug_window),
                    StructureNotifyMask | PropertyChangeMask);
       
+      if (gdk_error_trap_pop ())
+       {
+         gdk_window_unref (socket->plug_window);
+         socket->plug_window = NULL;
+         return;
+       }
+      
+      /* OK, we now will reliably get destroy notification on socket->plug_window */
+
+      gdk_error_trap_push ();
+
+      if (need_reparent)
+       {
+         gdk_window_hide (socket->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */
+         gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
+       }
+
+      socket->have_size = FALSE;
+
+      socket->xembed_version = -1;
+      if (xembed_get_info (socket->plug_window, &version, &flags))
+       {
+         socket->xembed_version = version;
+         socket->is_mapped = (flags & XEMBED_MAPPED) != 0;
+       }
+      else
+       {
+         /* FIXME, we should probably actually check the state before we started */
+         
+         socket->is_mapped = need_reparent ? TRUE : FALSE;
+       }
+      
+      socket->need_map = socket->is_mapped;
+
       if (gdk_drag_get_protocol (xid, &protocol))
        gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window, 
                                 protocol, TRUE);
+      
       gdk_flush ();
       gdk_error_trap_pop ();
 
@@ -864,9 +961,7 @@ gtk_socket_add_window (GtkSocket *socket, GdkNativeWindow xid)
 
       toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
       if (toplevel && GTK_IS_WINDOW (toplevel))
-       {
-         gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
-       }
+       gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
 
       gtk_widget_queue_resize (GTK_WIDGET (socket));
     }
@@ -907,6 +1002,58 @@ send_xembed_message (GtkSocket *socket,
     }
 }
 
+static gboolean
+xembed_get_info (GdkWindow     *gdk_window,
+                unsigned long *version,
+                unsigned long *flags)
+{
+  Display *display = GDK_WINDOW_XDISPLAY (gdk_window);
+  Window window = GDK_WINDOW_XWINDOW (gdk_window);
+  Atom xembed_info_atom = gdk_atom_intern ("_XEMBED_INFO", FALSE);
+  Atom type;
+  int format;
+  unsigned long nitems, bytes_after;
+  unsigned char *data;
+  unsigned long *data_long;
+  int status;
+  
+  gdk_error_trap_push();
+  status = XGetWindowProperty (display, window,
+                              xembed_info_atom,
+                              0, 2, False,
+                              xembed_info_atom, &type, &format,
+                              &nitems, &bytes_after, &data);
+  gdk_error_trap_pop();
+
+  if (status != Success)
+    return FALSE;              /* Window vanished? */
+
+  if (type == None)            /* No info property */
+    return FALSE;
+
+  if (type != xembed_info_atom)
+    {
+      g_warning ("_XEMBED_INFO property has wrong type\n");
+      return FALSE;
+    }
+  
+  if (nitems < 2)
+    {
+      g_warning ("_XEMBED_INFO too short\n");
+      XFree (data);
+      return FALSE;
+    }
+  
+  data_long = (unsigned long *)data;
+  if (version)
+    *version = data_long[0];
+  if (flags)
+    *flags = data_long[1] & XEMBED_MAPPED;
+  
+  XFree (data);
+  return TRUE;
+}
+
 static void
 handle_xembed_message (GtkSocket *socket,
                       glong      message,
@@ -962,6 +1109,28 @@ handle_xembed_message (GtkSocket *socket,
     }
 }
 
+static void
+map_request (GtkSocket *socket)
+{
+  if (!socket->is_mapped)
+    {
+      socket->is_mapped = TRUE;
+      socket->need_map = TRUE;
+
+      gtk_widget_queue_resize (GTK_WIDGET (socket));
+    }
+}
+
+static void
+unmap_notify (GtkSocket *socket)
+{
+  if (socket->is_mapped)
+    {
+      socket->is_mapped = FALSE;
+      gtk_widget_queue_resize (GTK_WIDGET (socket));
+    }
+}
+
 static GdkFilterReturn
 gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
 {
@@ -977,16 +1146,35 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
 
   return_val = GDK_FILTER_CONTINUE;
 
+  if (socket->plug_widget)
+    return return_val;
+
   switch (xevent->type)
     {
+    case ClientMessage:
+      if (xevent->xclient.message_type == gdk_atom_intern ("_XEMBED", FALSE))
+       {
+         handle_xembed_message (socket,
+                                xevent->xclient.data.l[1],
+                                xevent->xclient.data.l[2],
+                                xevent->xclient.data.l[3],
+                                xevent->xclient.data.l[4],
+                                xevent->xclient.data.l[0]);
+         
+         
+         return_val = GDK_FILTER_REMOVE;
+       }
+      break;
+
     case CreateNotify:
       {
        XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
 
        if (!socket->plug_window)
-         {
-           gtk_socket_add_window (socket, xcwe->window);
+         gtk_socket_add_window (socket, xcwe->window, FALSE);
 
+       if (socket->plug_window)
+         {
            gdk_error_trap_push ();
            gdk_window_move_resize(socket->plug_window,
                                   0, 0,
@@ -1015,9 +1203,9 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
        XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
        
        if (!socket->plug_window)
-         gtk_socket_add_window (socket, xcre->window);
+         gtk_socket_add_window (socket, xcre->window, FALSE);
        
-       if (xcre->window == GDK_WINDOW_XWINDOW (socket->plug_window))
+       if (socket->plug_window)
          {
            if (xcre->value_mask & (CWWidth | CWHeight))
              {
@@ -1047,8 +1235,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
       {
        XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
 
-       if (socket->plug_window &&
-           (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
+       if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
          {
            GtkWidget *toplevel;
 
@@ -1078,9 +1265,9 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
        {
 #if 0
          GtkWidget *toplevel;
-         toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+         toplevel = gtk_widget_get_toplevel (widget);
          
-         if (toplevel)
+         if (toplevel && GTK_IS_WINDOW (topelevel))
            {
              XSetInputFocus (GDK_DISPLAY (),
                              GDK_WINDOW_XWINDOW (toplevel->window),
@@ -1095,25 +1282,20 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
       break;
     case MapRequest:
       if (!socket->plug_window)
-       gtk_socket_add_window (socket, xevent->xmaprequest.window);
+       gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE);
        
-      if (xevent->xmaprequest.window ==
-         GDK_WINDOW_XWINDOW (socket->plug_window))
+      if (socket->plug_window)
        {
          GTK_NOTE(PLUGSOCKET,
                   g_message ("GtkSocket - Map Request"));
-         
-         gdk_error_trap_push ();
-         gdk_window_show (socket->plug_window);
-         gdk_flush ();
-         gdk_error_trap_pop ();
 
+         map_request (socket);
          return_val = GDK_FILTER_REMOVE;
        }
       break;
     case PropertyNotify:
-      if (xevent->xproperty.window ==
-         GDK_WINDOW_XWINDOW (socket->plug_window))
+      if (socket->plug_window &&
+         xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window))
        {
          GdkDragProtocol protocol;
 
@@ -1128,23 +1310,47 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
              gdk_flush ();
              gdk_error_trap_pop ();
            }
+         else if (xevent->xproperty.atom == gdk_atom_intern ("_XEMBED_INFO", FALSE))
+           {
+             unsigned long flags;
+             
+             if (xembed_get_info (socket->plug_window, NULL, &flags))
+               {
+                 gboolean was_mapped = socket->is_mapped;
+                 gboolean is_mapped = (flags & XEMBED_MAPPED) != 0;
+
+                 if (was_mapped != is_mapped)
+                   {
+                     if (is_mapped)
+                       map_request (socket);
+                     else
+                       {
+                         gdk_error_trap_push ();
+                         gdk_window_show (socket->plug_window);
+                         gdk_flush ();
+                         gdk_error_trap_pop ();
+                         
+                         unmap_notify (socket);
+                       }
+                   }
+               }
+           }
+                  
          return_val = GDK_FILTER_REMOVE;
        }
       break;
-    case ClientMessage:
-      if (xevent->xclient.message_type == gdk_atom_intern ("_XEMBED", FALSE))
+    case UnmapNotify:
+      if (socket->plug_window &&
+         xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window))
        {
-         handle_xembed_message (socket,
-                                xevent->xclient.data.l[1],
-                                xevent->xclient.data.l[2],
-                                xevent->xclient.data.l[3],
-                                xevent->xclient.data.l[4],
-                                xevent->xclient.data.l[0]);
-         
-         
+         GTK_NOTE(PLUGSOCKET,
+                  g_message ("GtkSocket - Unmap notify"));
+
+         unmap_notify (socket);
          return_val = GDK_FILTER_REMOVE;
        }
       break;
+      
     }
   
   return return_val;
index d6dc92d7104728c392bf94cb76fbf030461b2abe..18a762bbe952aadb4147c9ae5eea0bcce0eb817b 100644 (file)
@@ -54,10 +54,14 @@ struct _GtkSocket
   guint16 current_height;
   
   GdkWindow *plug_window;
+  GtkWidget *plug_widget;
+
+  gshort xembed_version;       /* -1 == not xembed */
   guint same_app : 1;
   guint focus_in : 1;
   guint have_size : 1;
   guint need_map : 1;
+  guint is_mapped : 1;
 
   GHashTable *grabbed_keys;
   GtkWidget *toplevel;
index 3a2848b5210fbad8a570267e7b1101d5316a2884..295855b89f04eb566ac29c35f5b7a7bd9d19af98 100644 (file)
@@ -4550,7 +4550,19 @@ gtk_widget_set_extension_events (GtkWidget *widget,
  *
  * Note the difference in behavior vs. gtk_widget_get_ancestor();
  * gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) would return
- * %NULL if @widget wasn't inside a toplevel window.
+ * %NULL if @widget wasn't inside a toplevel window, and if the
+ * window was inside a GtkWindow-derived widget which was in turn
+ * inside the toplevel GtkWindow. While the second case may
+ * seem unlikely, it actually happens when a GtkPlug is embedded
+ * inside a GtkSocket within the same application
+ * 
+ * To reliably find for the toplevel GtkWindow, use
+ * 
+ *  GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
+ *  if (GTK_IS_WINDOW (toplevel))
+ *   {
+ *     /* Perform action on toplevel.
+ *   }
  * 
  * Return value: the topmost ancestor of @widget, or @widget itself if there's no ancestor
  **/
@@ -4574,7 +4586,8 @@ gtk_widget_get_toplevel (GtkWidget *widget)
  * Gets the first ancestor of @widget with type @widget_type. For example,
  * gtk_widget_get_ancestor (widget, GTK_TYPE_BOX) gets the first #GtkBox that's
  * an ancestor of @widget. No reference will be added to the returned widget;
- * it should not be unreferenced.
+ * it should not be unreferenced. See note about checking for a toplevel
+ * GtkWindow in the docs for gtk_widget_get_toplevel().
  * 
  * Return value: the ancestor widget, or %NULL if not found
  **/
index 5c4e35d774386c573319f6d9bf7133892c27ce2c..d6de700f2a566c26415ea162f8ad77ee58ced536 100644 (file)
@@ -17,3 +17,6 @@
 #define XEMBED_FOCUS_FIRST              1
 #define XEMBED_FOCUS_LAST               2
 
+
+/* Flags for _XEMBED_INFO */
+#define XEMBED_MAPPED                   (1 << 0)
index 061f07133e1934df6cf4314686b48037b5acd344..47ac8b80964de2cac713522ca819e94b1329c476 100644 (file)
@@ -87,6 +87,14 @@ testtext_SOURCES =   \
        prop-editor.c   \
        testtext.c 
 
+testsocket_SOURCES =           \
+       testsocket.c            \
+       testsocket_common.c
+
+testsocket_child_SOURCES =     \
+       testsocket_child.c      \
+       testsocket_common.c
+
 EXTRA_DIST += @STRIP_BEGIN@    \
        prop-editor.h           \
        testgtk.1               \
index a775eefd382686bf6d5d2ad6f51f28f8d6524978..ab71501f1e397ba6da09c8ec639ccdf2df2fa362 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <unistd.h>
+
+int n_children = 0;
 
 GtkWidget *window;
 GtkWidget *vbox;
 GtkWidget *lastsocket = NULL;
 
+extern guint32 create_child_plug (guint32  xid,
+                                 gboolean local);
+
 static void
 quit_cb (gpointer        callback_data,
         guint           callback_action,
@@ -64,17 +70,66 @@ steal (GtkWidget *window, GtkEntry *entry)
 void
 remove_child (GtkWidget *window)
 {
-  if(lastsocket)
+  if (lastsocket)
     gtk_widget_destroy (lastsocket);
   lastsocket = NULL;
 }
 
+static gboolean
+child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data)
+{
+  GIOStatus status;
+  GError *error = NULL;
+  char *line;
+  gsize term;
+  int xid;
+  
+  status = g_io_channel_read_line (channel, &line, NULL, &term, &error);
+  switch (status)
+    {
+    case G_IO_STATUS_NORMAL:
+      line[term] = '\0';
+      xid = strtol (line, NULL, 0);
+      if (xid == 0)
+       {
+         fprintf (stderr, "Invalid window id '%s'\n", line);
+       }
+      else
+       {
+         GtkWidget *socket = gtk_socket_new ();
+         gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
+         gtk_widget_show (socket);
+         
+         gtk_socket_steal (GTK_SOCKET (socket), xid);
+       }
+      g_free (line);
+      return TRUE;
+    case G_IO_STATUS_AGAIN:
+      return TRUE;
+    case G_IO_STATUS_EOF:
+      n_children--;
+      g_io_channel_close (channel);
+      return FALSE;
+    case G_IO_STATUS_ERROR:
+      fprintf (stderr, "Error reading fd from child: %s\n", error->message);
+      exit (1);
+      return FALSE;
+    default:
+      g_assert_not_reached ();
+      return FALSE;
+    }
+  
+}
+
 void
-add_child (GtkWidget *window)
+add_child (GtkWidget *window,
+          gboolean   active)
 {
   GtkWidget *socket;
   char *argv[3] = { "./testsocket_child", NULL, NULL };
   char buffer[20];
+  int out_fd;
+  GIOChannel *channel;
   GError *error = NULL;
 
   socket = gtk_socket_new ();
@@ -83,20 +138,61 @@ add_child (GtkWidget *window)
 
   lastsocket = socket;
 
-  sprintf(buffer, "%#lx", GDK_WINDOW_XWINDOW (socket->window));
-  argv[1] = buffer;
+  if (active)
+    {
+      sprintf(buffer, "%#lx", GDK_WINDOW_XWINDOW (socket->window));
+      argv[1] = buffer;
+    }
   
 #if 1
-  if (!g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &error))
+  if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, &out_fd, NULL, &error))
     {
       fprintf (stderr, "Can't exec testsocket_child: %s\n", error->message);
       exit (1);
     }
+
+  n_children++;
+  channel = g_io_channel_unix_new (out_fd);
+  g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, &error);
+  if (error)
+    {
+      fprintf (stderr, "Error making channel non-blocking: %s\n", error->message);
+      exit (1);
+    }
+  
+  g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, NULL);
+  
 #else
   fprintf(stderr,"%s\n", buffer);
 #endif
 }
 
+void
+add_active_child (GtkWidget *window)
+{
+  add_child (window, TRUE);
+}
+
+void
+add_passive_child (GtkWidget *window)
+{
+  add_child (window, FALSE);
+}
+
+void
+add_local_child (GtkWidget *window)
+{
+  GtkWidget *socket;
+
+  socket = gtk_socket_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
+  gtk_widget_show (socket);
+
+  lastsocket = socket;
+
+  create_child_plug (GDK_WINDOW_XWINDOW (socket->window), TRUE);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -131,11 +227,25 @@ main (int argc, char *argv[])
                      gtk_item_factory_get_widget (item_factory, "<main>"),
                      FALSE, FALSE, 0);
 
-  button = gtk_button_new_with_label ("Add Child");
+  button = gtk_button_new_with_label ("Add Active Child");
   gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
 
   gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
-                            GTK_SIGNAL_FUNC(add_child),
+                            GTK_SIGNAL_FUNC(add_active_child),
+                            GTK_OBJECT(vbox));
+
+  button = gtk_button_new_with_label ("Add Passive Child");
+  gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
+
+  gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
+                            GTK_SIGNAL_FUNC(add_passive_child),
+                            GTK_OBJECT(vbox));
+
+  button = gtk_button_new_with_label ("Add Local Child");
+  gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
+
+  gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
+                            GTK_SIGNAL_FUNC(add_local_child),
                             GTK_OBJECT(vbox));
 
   button = gtk_button_new_with_label ("Remove Last Child");
@@ -162,7 +272,13 @@ main (int argc, char *argv[])
 
   gtk_main ();
 
-  return 0;
-}
+  if (n_children)
+    {
+      g_print ("Waiting for children to exit\n");
 
+      while (n_children)
+       g_main_iteration (TRUE);
+    }
 
+  return 0;
+}
index 084e71a917b4b5bdf47ad98972fa3e8d13fea8f9..ae24efd89201a94f02a87d4caa58bebbad2dfb32 100644 (file)
@@ -3,84 +3,40 @@
 
 #include <gtk/gtk.h>
 
-void
-remove_buttons (GtkWidget *widget, GtkWidget *other_button)
-{
-  gtk_widget_destroy (other_button);
-  gtk_widget_destroy (widget);
-}
-
-void
-add_buttons (GtkWidget *widget, GtkWidget *box)
-{
-  GtkWidget *add_button;
-  GtkWidget *remove_button;
-
-  add_button = gtk_button_new_with_mnemonic ("_Add");
-  gtk_box_pack_start (GTK_BOX (box), add_button, TRUE, TRUE, 0);
-  gtk_widget_show (add_button);
-
-  gtk_signal_connect (GTK_OBJECT (add_button), "clicked",
-                     GTK_SIGNAL_FUNC (add_buttons),
-                     box);
-
-  remove_button = gtk_button_new_with_mnemonic ("_Remove");
-  gtk_box_pack_start (GTK_BOX (box), remove_button, TRUE, TRUE, 0);
-  gtk_widget_show (remove_button);
-
-  gtk_signal_connect (GTK_OBJECT (remove_button), "clicked",
-                     GTK_SIGNAL_FUNC (remove_buttons),
-                     add_button);
-}
+extern guint32 create_child_plug (guint32  xid,
+                                 gboolean local);
 
 int
 main (int argc, char *argv[])
 {
   guint32 xid;
+  guint32 plug_xid;
 
-  GtkWidget *window;
-  GtkWidget *hbox;
-  GtkWidget *entry;
-  GtkWidget *button;
   gtk_init (&argc, &argv);
 
-  if (argc < 2)
+  if (argc != 1 && argc != 2)
     {
-      fprintf (stderr, "Usage: testsocket_child WINDOW_ID\n");
+      fprintf (stderr, "Usage: testsocket_child [WINDOW_ID]\n");
       exit (1);
     }
 
-  xid = strtol (argv[1], NULL, 0);
-  if (xid == 0)
+  if (argc == 2)
     {
-      fprintf (stderr, "Invalid window id '%s'\n", argv[1]);
-      exit (1);
+      xid = strtol (argv[1], NULL, 0);
+      if (xid == 0)
+       {
+         fprintf (stderr, "Invalid window id '%s'\n", argv[1]);
+         exit (1);
+       }
+      
+      create_child_plug (xid, FALSE);
+    }
+  else
+    {
+      plug_xid = create_child_plug (0, FALSE);
+      printf ("%d\n", plug_xid);
+      fflush (stdout);
     }
-
-  window = gtk_plug_new (xid);
-  gtk_signal_connect (GTK_OBJECT (window), "destroy",
-                     (GtkSignalFunc) gtk_exit, NULL);
-  gtk_container_set_border_width (GTK_CONTAINER (window), 0);
-
-  hbox = gtk_hbox_new (FALSE, 0);
-  gtk_container_add (GTK_CONTAINER (window), hbox);
-  gtk_widget_show (hbox);
-
-  entry = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
-  gtk_widget_show (entry);
-
-  button = gtk_button_new_with_mnemonic ("_Close");
-  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
-  gtk_widget_show (button);
-
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-                            GTK_SIGNAL_FUNC (gtk_widget_destroy),
-                            GTK_OBJECT (window));
-
-  add_buttons (NULL, hbox);
-  
-  gtk_widget_show (window);
 
   gtk_main ();