Index: tests/testsocket.c
===================================================================
RCS file: /cvs/gnome/gtk+/tests/testsocket.c,v
retrieving revision 1.16
diff -p -u -2 -r1.16 testsocket.c
--- tests/testsocket.c	28 Oct 2004 15:00:05 -0000	1.16
+++ tests/testsocket.c	17 Mar 2005 00:36:10 -0000
@@ -103,5 +103,4 @@ create_socket (void)
   sockets = g_slist_prepend (sockets, socket);
 
-
   g_signal_connect (socket->socket, "destroy",
 		    G_CALLBACK (socket_destroyed), socket);
@@ -171,5 +170,5 @@ child_read_watch (GIOChannel *channel, G
 	  gtk_box_pack_start (GTK_BOX (box), socket->box, TRUE, TRUE, 0);
 	  gtk_widget_show (socket->box);
-	  
+	  fprintf (stderr, "testsocket: xid=%#x\n", xid);
 	  gtk_socket_add_id (GTK_SOCKET (socket->socket), xid);
 	}
@@ -212,22 +211,48 @@ add_child (GtkWidget *window,
     }
   
+  if (getenv ("TESTSOCKET_DEBUG"))
+    {
+      fprintf (stderr, "================ Now run %s%s%s (in another window)\n",
+	       argv[0], (argv[1] ? " " : ""), (argv[1] ? argv[1] : ""));
+      if (!active)
+	{
+	  Socket *socket;
+	  int xid;
+
+	  fprintf (stderr, "Please enter the number it prints:\n");
+	  fflush (stderr);
+
+	  scanf ("%d", &xid);
+
+	  socket = create_socket ();
+	  gtk_box_pack_start (GTK_BOX (box), socket->box, TRUE, TRUE, 0);
+	  gtk_widget_show (socket->box);
+	  gtk_socket_add_id (GTK_SOCKET (socket->socket), xid);
+	}
+      return;
+    }
+
   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);
+      fprintf (stderr, "Can't spawn testsocket_child: %s\n", error->message);
       exit (1);
     }
 
-  n_children++;
-  channel = g_io_channel_unix_new (out_fd);
-  g_io_channel_set_close_on_unref (channel, TRUE);
-  g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, &error);
-  if (error)
+  if (!active)
     {
-      fprintf (stderr, "Error making channel non-blocking: %s\n", error->message);
-      exit (1);
+      channel = g_io_channel_unix_new (out_fd);
+      g_io_channel_set_close_on_unref (channel, TRUE);
+      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);
+	}
+      
+      n_children++;
+
+      g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, NULL);
+      g_io_channel_unref (channel);
     }
-  
-  g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, NULL);
-  g_io_channel_unref (channel);
 }
 
Index: tests/testsocket_common.c
===================================================================
RCS file: /cvs/gnome/gtk+/tests/testsocket_common.c,v
retrieving revision 1.6
diff -p -u -2 -r1.6 testsocket_common.c
--- tests/testsocket_common.c	28 Oct 2004 15:00:05 -0000	1.6
+++ tests/testsocket_common.c	17 Mar 2005 00:36:11 -0000
@@ -2,6 +2,10 @@
 
 #include <config.h>
-#include "x11/gdkx.h"
 #include <gtk/gtk.h>
+#if defined (GDK_WINDOWING_X11)
+#include "x11/gdkx.h"
+#elif defined (GDK_WINDOWING_WIN32)
+#include "win32/gdkwin32.h"
+#endif
 
 enum
@@ -242,8 +246,14 @@ create_child_plug (guint32  xid,
   gtk_container_add (GTK_CONTAINER (window), content);
 
+  fprintf (stderr, "create_child_plug: calling gtk_widget_show_all\n"); fflush (stderr);
   gtk_widget_show_all (window);
+  fprintf (stderr, "create_child_plug: called gtk_widget_show_all\n"); fflush (stderr);
 
   if (GTK_WIDGET_REALIZED (window))
+#if defined (GDK_WINDOWING_X11)
     return GDK_WINDOW_XID (window->window);
+#elif defined (GDK_WINDOWING_WIN32)
+    return (guint32) GDK_WINDOW_HWND (window->window);
+#endif
   else
     return 0;
Index: gtk/Makefile.am
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/Makefile.am,v
retrieving revision 1.268
diff -p -u -2 -r1.268 Makefile.am
--- gtk/Makefile.am	13 Jan 2005 15:19:27 -0000	1.268
+++ gtk/Makefile.am	17 Mar 2005 00:36:11 -0000
@@ -304,6 +304,8 @@ gtk_private_h_sources =		\
 	gtkiconcache.h		\
 	gtkpathbar.h		\
+	gtkplugprivate.h	\
 	gtkrbtree.h		\
 	gtksequence.h		\
+	gtksocketprivate.h	\
 	gtktextbtree.h		\
 	gtktextchildprivate.h	\
@@ -440,4 +442,5 @@ gtk_c_sources =                 \
 	gtkpathbar.c		\
 	gtkpixmap.c		\
+	gtkplug.c		\
 	gtkpreview.c		\
 	gtkprogress.c		\
@@ -462,4 +465,5 @@ gtk_c_sources =                 \
 	gtksignal.c		\
 	gtksizegroup.c		\
+	gtksocket.c		\
 	gtkspinbutton.c		\
 	gtkstatusbar.c		\
@@ -522,19 +526,13 @@ gtk_c_sources =                 \
 
 if OS_UNIX
-gtk_private_h_sources += gtkfilesystemunix.h
-gtk_c_sources +=         gtkfilesystemunix.c
+gtk_private_h_sources += gtkfilesystemunix.h gtkxembed.h
+gtk_c_sources +=         gtkfilesystemunix.c gtkplug-x11.c gtksocket-x11.c gtkxembed.c
 endif
 
 if OS_WIN32
-gtk_private_h_sources += gtkfilesystemwin32.h
-gtk_c_sources +=         gtkfilesystemwin32.c
+gtk_private_h_sources += gtkfilesystemwin32.h gtkwin32embed.h
+gtk_c_sources +=         gtkfilesystemwin32.c gtkplug-win32.c gtksocket-win32.c gtkwin32embed.c
 endif
 
-gtk_plug_c_sources =            \
-	gtkplug.c		\
-	gtksocket.c		\
-	gtkxembed.c		\
-	gtkxembed.h
-
 # we use our own built_sources variable rules to avoid automake's
 # BUILT_SOURCES oddities
@@ -652,5 +650,5 @@ gtkincludedir = $(includedir)/gtk-2.0/gt
 gtkinclude_HEADERS = $(gtk_public_h_sources) $(gtk_semi_private_h_sources) $(gtk_built_public_sources) gtkversion.h
 
-libgtk_x11_2_0_la_SOURCES = $(gtk_c_sources) $(gtk_plug_c_sources)
+libgtk_x11_2_0_la_SOURCES = $(gtk_c_sources)
 libgtk_linux_fb_2_0_la_SOURCES = $(gtk_c_sources)
 libgtk_win32_2_0_la_SOURCES = $(gtk_c_sources)
Index: gtk/gtk.symbols
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtk.symbols,v
retrieving revision 1.31
diff -p -u -2 -r1.31 gtk.symbols
--- gtk/gtk.symbols	8 Mar 2005 06:10:31 -0000	1.31
+++ gtk/gtk.symbols	17 Mar 2005 00:36:12 -0000
@@ -1647,5 +1647,4 @@ gtk_pixmap_new
 gtk_pixmap_set
 gtk_pixmap_set_build_insensitive
-#ifdef GTK_WINDOWING_X11
 gtk_plug_construct
 gtk_plug_construct_for_display
@@ -1654,5 +1653,4 @@ gtk_plug_get_type G_GNUC_CONST
 gtk_plug_new
 gtk_plug_new_for_display
-#endif
 gtk_policy_type_get_type G_GNUC_CONST
 gtk_position_type_get_type G_GNUC_CONST
@@ -1901,5 +1899,4 @@ gtk_size_group_new
 gtk_size_group_remove_widget
 gtk_size_group_set_mode
-#ifdef GTK_WINDOWING_X11
 gtk_socket_add_id
 gtk_socket_get_id
@@ -1907,5 +1904,4 @@ gtk_socket_get_type G_GNUC_CONST
 gtk_socket_new
 gtk_socket_steal
-#endif
 gtk_sort_type_get_type G_GNUC_CONST
 gtk_spin_button_configure
Index: gtk/gtkplug-win32.c
===================================================================
RCS file: gtk/gtkplug-win32.c
diff -N gtk/gtkplug-win32.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkplug-win32.c	17 Mar 2005 00:36:12 -0000
@@ -0,0 +1,311 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 2005 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* By Tor Lillqvist <tml@novell.com> 2005 */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2005.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include "gtkmarshalers.h"
+#include "gtkplug.h"
+#include "gtkplugprivate.h"
+
+#include "win32/gdkwin32.h"
+
+#include "gtkwin32embed.h"
+
+GdkNativeWindow
+gtk_plug_get_id (GtkPlug *plug)
+{
+  g_return_val_if_fail (GTK_IS_PLUG (plug), 0);
+
+  if (!GTK_WIDGET_REALIZED (plug))
+    gtk_widget_realize (GTK_WIDGET (plug));
+
+  return (GdkNativeWindow) GDK_WINDOW_HWND (GTK_WIDGET (plug)->window);
+}
+
+void
+_gtk_plug_realize_toplevel (GdkWindow *plug_window,
+			    GdkWindow *socket_window)
+{
+  fprintf (stderr, "%s plug=%p socket=%p\n",
+	   __FUNCTION__,
+	   GDK_WINDOW_HWND (plug_window),
+	   (socket_window ? GDK_WINDOW_HWND (socket_window) : 0));
+  fflush (stderr);
+
+  if (socket_window)
+    _gtk_win32_embed_send (socket_window, GTK_WIN32_EMBED_EVENT_PLUG_MAPPED, 0, 0);
+}
+
+void
+_gtk_plug_map_toplevel (GdkWindow *plug_window,
+			GdkWindow *socket_window)
+{
+  fprintf (stderr, "%s plug=%p socket=%p\n",
+	   __FUNCTION__,
+	   GDK_WINDOW_HWND (plug_window),
+	   (socket_window ? GDK_WINDOW_HWND (socket_window) : 0));
+  fflush (stderr);
+
+  if (socket_window)
+    _gtk_win32_embed_send (socket_window, GTK_WIN32_EMBED_EVENT_PLUG_MAPPED, 1, 0);
+}
+
+void
+_gtk_plug_unmap_toplevel (GdkWindow *plug_window,
+			  GdkWindow *socket_window)
+{
+  fprintf (stderr, "%s plug=%p socket=%p\n",
+	   __FUNCTION__,
+	   GDK_WINDOW_HWND (plug_window),
+	   (socket_window ? GDK_WINDOW_HWND (socket_window) : 0));
+  fflush (stderr);
+
+  if (socket_window)
+    _gtk_win32_embed_send (socket_window, GTK_WIN32_EMBED_EVENT_PLUG_MAPPED,
+			   0, 0);
+}
+
+void
+_gtk_plug_set_focus (GdkWindow *socket_window)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  _gtk_win32_embed_send (socket_window, GTK_WIN32_EMBED_REQUEST_FOCUS,
+			 0, 0);
+}
+
+void
+_gtk_plug_add_grabbed_key (GdkWindow      *socket_window,
+			   guint           accelerator_key,
+			   GdkModifierType accelerator_mods)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  _gtk_win32_embed_send (socket_window, GTK_WIN32_EMBED_GRAB_KEY,
+			 accelerator_key, accelerator_mods);
+}
+
+void
+_gtk_plug_remove_grabbed_key (GdkWindow *socket_window,
+			      guint accelerator_key,
+			      GdkModifierType accelerator_mods)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  _gtk_win32_embed_send (socket_window, GTK_WIN32_EMBED_UNGRAB_KEY,
+			 accelerator_key, accelerator_mods);
+}
+
+void
+_gtk_plug_focus_to_parent (GdkWindow       *socket_window,
+			   GtkDirectionType direction)
+{
+  GtkWin32EmbedMessageType message = GTK_WIN32_EMBED_FOCUS_PREV;
+  
+#define CASE(x) direction == GTK_DIR_##x ? #x
+  fprintf (stderr, "%s: %s\n", __FUNCTION__,
+	   (CASE (UP) :
+	    (CASE (LEFT) :
+	     (CASE (TAB_BACKWARD) :
+	      (CASE (DOWN) :
+	       (CASE (RIGHT) :
+		(CASE (TAB_FORWARD) : "???")))))));
+  fflush (stderr);
+#undef CASE
+
+  switch (direction)
+    {
+    case GTK_DIR_UP:
+    case GTK_DIR_LEFT:
+    case GTK_DIR_TAB_BACKWARD:
+      message = GTK_WIN32_EMBED_FOCUS_PREV;
+      break;
+    case GTK_DIR_DOWN:
+    case GTK_DIR_RIGHT:
+    case GTK_DIR_TAB_FORWARD:
+      message = GTK_WIN32_EMBED_FOCUS_NEXT;
+      break;
+    }
+  
+  _gtk_win32_embed_send_focus_message (socket_window, message, 0);
+}
+
+GdkFilterReturn
+_gtk_plug_filter_func (GdkXEvent *gdk_xevent,
+		       GdkEvent  *event,
+		       gpointer   data)
+{
+  GdkScreen *screen = gdk_drawable_get_screen (event->any.window);
+  GdkDisplay *display = gdk_screen_get_display (screen);
+  HWND root = GDK_WINDOW_HWND (gdk_screen_get_root_window (screen));
+  GtkPlug *plug = GTK_PLUG (data);
+  MSG *msg = (MSG *) gdk_xevent;
+  GdkFilterReturn return_val = GDK_FILTER_CONTINUE;
+
+  fprintf (stderr, "%s: ", __FUNCTION__); fflush (stderr);
+
+  switch (msg->message)
+    {
+    default:
+      if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_REQUEST_EVENTS))
+	{
+	  gboolean was_embedded = plug->socket_window != NULL;
+
+	  fprintf (stderr, "REQUEST_EVENTS: was_embedded:%d: ", was_embedded); fflush (stderr);
+	  _gtk_win32_embed_push_message (msg);
+	  g_object_ref (plug);
+
+	  if (was_embedded)
+	    {
+	      /* End of embedding protocol for previous socket */
+	    
+	      if (msg->wParam != (WPARAM) GDK_WINDOW_HWND (plug->socket_window))
+		{
+		  GtkWidget *widget = GTK_WIDGET (plug);
+		  
+		  gdk_window_set_user_data (plug->socket_window, NULL);
+		  g_object_unref (plug->socket_window);
+		  plug->socket_window = NULL;
+		  
+		  /* Emit a delete window, as if the user attempted to
+		   * close the toplevel if we are being reparented to
+		   * the root window. Moving from one embedder to
+		   * another should be invisible to the app.
+		   */
+		  if (msg->wParam == (WPARAM) root)
+		    _gtk_plug_send_delete_event (widget);
+		}
+	      else
+		goto done;
+	    }
+
+	  if (msg->wParam != (WPARAM) root)
+	    {
+	      /* Start of embedding protocol */
+
+	      fprintf (stderr, "not root: "); fflush (stderr);
+	      plug->socket_window = gdk_window_lookup_for_display (display, msg->wParam);
+	      if (plug->socket_window)
+		{
+		  gpointer user_data = NULL;
+		  gdk_window_get_user_data (plug->socket_window, &user_data);
+
+		  if (user_data)
+		    {
+		      g_warning (G_STRLOC ": Plug reparented unexpectedly into window in the same process");
+		      plug->socket_window = NULL;
+		      break;
+		    }
+
+		  g_object_ref (plug->socket_window);
+		}
+	      else
+		{
+		  plug->socket_window = gdk_window_foreign_new_for_display (display, msg->wParam);
+		  if (!plug->socket_window) /* Already gone */
+		    break;
+		}
+
+	      if (plug->grabbed_keys)
+		g_hash_table_foreach (plug->grabbed_keys,
+				      _gtk_plug_add_grabbed_key_always,
+				      plug);
+
+	      if (!was_embedded)
+		g_signal_emit (plug, _gtk_plug_signals[EMBEDDED], 0);
+	    }
+	done:
+	  g_object_unref (plug);
+	  
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_WINDOW_ACTIVATE))
+	{
+	  fprintf (stderr, "WINDOW_ACTIVATE: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_window_set_is_active (GTK_WINDOW (plug), TRUE);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_WINDOW_DEACTIVATE))
+	{
+	  fprintf (stderr, "WINDOW_DEACTIVATE: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_window_set_is_active (GTK_WINDOW (plug), FALSE);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_IN))
+	{
+	  fprintf (stderr, "FOCUS_IN: %d", msg->wParam);
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_window_set_has_toplevel_focus (GTK_WINDOW (plug), TRUE);
+	  switch (msg->wParam)
+	    {
+	    case GTK_WIN32_EMBED_FOCUS_CURRENT:
+	      fprintf (stderr, "CURRENT: ");
+	      break;
+	    case GTK_WIN32_EMBED_FOCUS_FIRST:
+	      fprintf (stderr, "FIRST: ");
+	      _gtk_plug_focus_first_last (plug, GTK_DIR_TAB_FORWARD);
+	      break;
+	    case GTK_WIN32_EMBED_FOCUS_LAST:
+	      fprintf (stderr, "LAST: ");
+	      _gtk_plug_focus_first_last (plug, GTK_DIR_TAB_BACKWARD);
+	      break;
+	    }
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->wParam == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_OUT))
+	{
+	  fprintf (stderr, "FOCUS_OUT: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_window_set_has_toplevel_focus (GTK_WINDOW (plug), FALSE);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->wParam == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_MODALITY_ON))
+	{
+	  fprintf (stderr, "MODALITY_ON: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_plug_handle_modality_on (plug);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->wParam == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_MODALITY_OFF))
+	{
+	  fprintf (stderr, "MODALITY_OFF: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_plug_handle_modality_off (plug);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      break;
+    }
+
+  fprintf (stderr, "\n"); fflush (stderr);
+
+  return return_val;
+}
Index: gtk/gtkplug-x11.c
===================================================================
RCS file: gtk/gtkplug-x11.c
diff -N gtk/gtkplug-x11.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkplug-x11.c	17 Mar 2005 00:36:13 -0000
@@ -0,0 +1,368 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* By Owen Taylor <otaylor@gtk.org>              98/4/4 */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include "gtkalias.h"
+#include "gtkmain.h"
+#include "gtkmarshalers.h"
+#include "gtkplug.h"
+#include "gtkprivate.h"
+#include "gtkplugprivate.h"
+
+#include "x11/gdkx.h"
+
+#include "gtkxembed.h"
+
+static void xembed_set_info            (GdkWindow     *window,
+					unsigned long  flags);
+
+/**
+ * gtk_plug_get_id:
+ * @plug: a #GtkPlug.
+ * 
+ * Gets the window ID of a #GtkPlug widget, which can then
+ * be used to embed this window inside another window, for
+ * instance with gtk_socket_add_id().
+ * 
+ * Return value: the window ID for the plug
+ **/
+GdkNativeWindow
+gtk_plug_get_id (GtkPlug *plug)
+{
+  g_return_val_if_fail (GTK_IS_PLUG (plug), 0);
+
+  if (!GTK_WIDGET_REALIZED (plug))
+    gtk_widget_realize (GTK_WIDGET (plug));
+
+  return GDK_WINDOW_XWINDOW (GTK_WIDGET (plug)->window);
+}
+
+void
+_gtk_plug_realize_toplevel (GdkWindow *plug_window,
+			    GdkWindow *socket_window)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  xembed_set_info (plug_window, 0);
+}
+
+void
+_gtk_plug_map_toplevel (GdkWindow *plug_window,
+			GdkWindow *socket_window)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  xembed_set_info (plug_window, XEMBED_MAPPED);
+}
+
+void
+_gtk_plug_unmap_toplevel (GdkWindow *plug_window,
+			  GdkWindow *socket_window)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  xembed_set_info (plug_window, 0);
+}
+
+void
+_gtk_plug_set_focus (GdkWindow *socket_window)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  _gtk_xembed_send_message (socket_window,
+			    XEMBED_REQUEST_FOCUS, 0, 0, 0);
+}
+
+void
+_gtk_plug_add_grabbed_key (GdkWindow      *socket_window,
+			   guint           accelerator_key,
+			   GdkModifierType accelerator_mods)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  _gtk_xembed_send_message (socket_window, XEMBED_GTK_GRAB_KEY, 0, 
+			    accelerator_key, accelerator_mods);
+}
+
+void
+_gtk_plug_remove_grabbed_key (GdkWindow      *socket_window,
+			      guint           accelerator_key,
+			      GdkModifierType accelerator_mods)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  _gtk_xembed_send_message (socket_window, XEMBED_GTK_UNGRAB_KEY, 0, 
+			    accelerator_key, accelerator_mods);
+}
+
+void
+_gtk_plug_focus_to_parent (GdkWindow       *socket_window,
+			   GtkDirectionType direction)
+{
+  XEmbedMessageType message = XEMBED_FOCUS_PREV; /* Quiet GCC */
+  
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  switch (direction)
+    {
+    case GTK_DIR_UP:
+    case GTK_DIR_LEFT:
+    case GTK_DIR_TAB_BACKWARD:
+      message = XEMBED_FOCUS_PREV;
+      break;
+    case GTK_DIR_DOWN:
+    case GTK_DIR_RIGHT:
+    case GTK_DIR_TAB_FORWARD:
+      message = XEMBED_FOCUS_NEXT;
+      break;
+    }
+  
+  _gtk_xembed_send_focus_message (socket_window, message, 0);
+}
+
+static void
+xembed_set_info (GdkWindow     *window,
+		 unsigned long  flags)
+{
+  GdkDisplay *display = gdk_drawable_get_display (window);
+  unsigned long buffer[2];
+
+  Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
+
+  buffer[0] = GTK_XEMBED_PROTOCOL_VERSION;
+  buffer[1] = flags;
+
+  XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+		   GDK_WINDOW_XWINDOW (window),
+		   xembed_info_atom, xembed_info_atom, 32,
+		   PropModeReplace,
+		   (unsigned char *)buffer, 2);
+}
+
+static void
+handle_xembed_message (GtkPlug           *plug,
+		       XEmbedMessageType  message,
+		       glong              detail,
+		       glong              data1,
+		       glong              data2,
+		       guint32            time)
+{
+  GtkWindow *window = GTK_WINDOW (plug);
+
+  GTK_NOTE (PLUGSOCKET,
+	    g_message ("GtkPlug: Message of type %d received", message));
+  
+  switch (message)
+    {
+    case XEMBED_EMBEDDED_NOTIFY:
+      break;
+    case XEMBED_WINDOW_ACTIVATE:
+      fprintf (stderr, "XEMBED_WINDOW_ACTIVATE ");
+      _gtk_window_set_is_active (window, TRUE);
+      break;
+    case XEMBED_WINDOW_DEACTIVATE:
+      fprintf (stderr, "XEMBED_WINDOW_DEACTIVATE ");
+      _gtk_window_set_is_active (window, FALSE);
+      break;
+      
+    case XEMBED_MODALITY_ON:
+      fprintf (stderr, "XEMBED_MODALITY_ON ");
+      _gtk_plug_handle_modality_on (plug);
+      break;
+    case XEMBED_MODALITY_OFF:
+      fprintf (stderr, "XEMBED_MODALITY_OFF ");
+      _gtk_plug_handle_modality_off (plug);
+      break;
+
+    case XEMBED_FOCUS_IN:
+      fprintf (stderr, "XEMBED_FOCUS_IN ");
+      _gtk_window_set_has_toplevel_focus (window, TRUE);
+      switch (detail)
+	{
+	case XEMBED_FOCUS_FIRST:
+	  fprintf (stderr, "XEMBED_FOCUS_FIRST ");
+	  _gtk_plug_focus_first_last (plug, GTK_DIR_TAB_FORWARD);
+	  break;
+	case XEMBED_FOCUS_LAST:
+	  fprintf (stderr, "XEMBED_FOCUS_LAST ");
+	  _gtk_plug_focus_first_last (plug, GTK_DIR_TAB_BACKWARD);
+	  break;
+	case XEMBED_FOCUS_CURRENT:
+	  break;
+	}
+      break;
+
+    case XEMBED_FOCUS_OUT:
+      fprintf (stderr, "XEMBED_FOCUS_OUT ");
+      _gtk_window_set_has_toplevel_focus (window, FALSE);
+      break;
+      
+    case XEMBED_GRAB_KEY:
+    case XEMBED_UNGRAB_KEY:
+    case XEMBED_GTK_GRAB_KEY:
+    case XEMBED_GTK_UNGRAB_KEY:
+    case XEMBED_REQUEST_FOCUS:
+    case XEMBED_FOCUS_NEXT:
+    case XEMBED_FOCUS_PREV:
+      g_warning ("GtkPlug: Invalid _XEMBED message of type %d received", message);
+      break;
+      
+    default:
+      GTK_NOTE(PLUGSOCKET,
+	       g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %d", message));
+      break;
+    }
+}
+
+GdkFilterReturn
+_gtk_plug_filter_func (GdkXEvent *gdk_xevent,
+		       GdkEvent  *event,
+		       gpointer   data)
+{
+  GdkScreen *screen = gdk_drawable_get_screen (event->any.window);
+  GdkDisplay *display = gdk_screen_get_display (screen);
+  GtkPlug *plug = GTK_PLUG (data);
+  XEvent *xevent = (XEvent *)gdk_xevent;
+
+  GdkFilterReturn return_val;
+  
+  return_val = GDK_FILTER_CONTINUE;
+
+  fprintf (stderr, "_gtk_plug_filter_func: "); fflush (stderr);
+
+  switch (xevent->type)
+    {
+    case ClientMessage:
+      fprintf (stderr, "ClientMessage: "); fflush (stderr);
+      if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"))
+	{
+	  fprintf (stderr, "_XEMBED: "); fflush (stderr);
+	  _gtk_xembed_push_message (xevent);
+	  handle_xembed_message (plug,
+				 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_xembed_pop_message ();
+
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
+	{
+	  fprintf (stderr, "WM_DELETE_WINDOW: "); fflush (stderr);
+	  /* We filter these out because we take being reparented back to the
+	   * root window as the reliable end of the embedding protocol
+	   */
+
+	  return GDK_FILTER_REMOVE;
+	}
+      break;
+    case ReparentNotify:
+      fprintf (stderr, "ReparentNotify: "); fflush (stderr);
+      {
+	XReparentEvent *xre = &xevent->xreparent;
+	gboolean was_embedded = plug->socket_window != NULL;
+
+	fprintf (stderr, "was_embedded:%d ", was_embedded); fflush (stderr);
+	return_val = GDK_FILTER_REMOVE;
+	
+	g_object_ref (plug);
+	
+	if (was_embedded)
+	  {
+	    /* End of embedding protocol for previous socket */
+	    
+	    /* FIXME: race if we remove from another socket and
+	     * then add to a local window before we get notification
+	     * Probably need check in _gtk_plug_add_to_socket
+	     */
+	    
+	    if (xre->parent != GDK_WINDOW_XWINDOW (plug->socket_window))
+	      {
+		GtkWidget *widget = GTK_WIDGET (plug);
+
+		fprintf (stderr, "parent!=socket_window: "); fflush (stderr);
+		gdk_window_set_user_data (plug->socket_window, NULL);
+		g_object_unref (plug->socket_window);
+		plug->socket_window = NULL;
+
+		/* Emit a delete window, as if the user attempted
+		 * to close the toplevel. Simple as to how we
+		 * handle WM_DELETE_WINDOW, if it isn't handled
+		 * we destroy the widget. BUt only do this if
+		 * we are being reparented to the root window.
+		 * Moving from one embedder to another should
+		 * be invisible to the app.
+		 */
+
+		if (xre->parent == GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)))
+		  _gtk_plug_send_delete_event (widget);
+	      }
+	    else
+	      goto done;
+	  }
+
+	if (xre->parent != GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)))
+	  {
+	    /* Start of embedding protocol */
+
+	    fprintf (stderr, "parent!=root: "); fflush (stderr);
+	    plug->socket_window = gdk_window_lookup_for_display (display, xre->parent);
+	    if (plug->socket_window)
+	      {
+		gpointer user_data = NULL;
+		fprintf (stderr, "have socket_window: "); fflush (stderr);
+		gdk_window_get_user_data (plug->socket_window, &user_data);
+
+		if (user_data)
+		  {
+		    g_warning (G_STRLOC "Plug reparented unexpectedly into window in the same process");
+		    plug->socket_window = NULL;
+		    break;
+		  }
+
+		g_object_ref (plug->socket_window);
+	      }
+	    else
+	      {
+		plug->socket_window = gdk_window_foreign_new_for_display (display, xre->parent);
+		if (!plug->socket_window) /* Already gone */
+		  break;
+	      }
+
+	    if (plug->grabbed_keys)
+	      g_hash_table_foreach (plug->grabbed_keys,
+				    _gtk_plug_add_grabbed_key_always,
+				    plug);
+
+	    if (!was_embedded)
+	      g_signal_emit (plug, _gtk_plug_signals[EMBEDDED], 0);
+	  }
+
+      done:
+	g_object_unref (plug);
+	
+	break;
+      }
+    }
+
+  fprintf (stderr, "\n"); fflush (stderr);
+  return GDK_FILTER_CONTINUE;
+}
Index: gtk/gtkplug.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkplug.c,v
retrieving revision 1.67
diff -p -u -2 -r1.67 gtkplug.c
--- gtk/gtkplug.c	28 Oct 2004 15:00:04 -0000	1.67
+++ gtk/gtkplug.c	17 Mar 2005 00:36:13 -0000
@@ -26,4 +26,6 @@
  */
 
+#include "gdkconfig.h"
+
 #include "gtkalias.h"
 #include "gtkmain.h"
@@ -31,9 +33,5 @@
 #include "gtkplug.h"
 #include "gtkprivate.h"
-
-#include "gdk/gdkkeysyms.h"
-#include "x11/gdkx.h"
-
-#include "gtkxembed.h"
+#include "gtkplugprivate.h"
 
 static void            gtk_plug_class_init            (GtkPlugClass     *klass);
@@ -58,11 +56,4 @@ static gboolean        gtk_plug_focus   
 static void            gtk_plug_check_resize          (GtkContainer     *container);
 static void            gtk_plug_keys_changed          (GtkWindow        *window);
-static GdkFilterReturn gtk_plug_filter_func           (GdkXEvent        *gdk_xevent,
-						       GdkEvent         *event,
-						       gpointer          data);
-
-static void handle_modality_off        (GtkPlug       *plug);
-static void xembed_set_info            (GdkWindow     *window,
-					unsigned long  flags);
 
 /* From Tk */
@@ -72,10 +63,5 @@ static GtkWindowClass *parent_class = NU
 static GtkBinClass *bin_class = NULL;
 
-enum {
-  EMBEDDED,
-  LAST_SIGNAL
-}; 
-
-static guint plug_signals[LAST_SIGNAL] = { 0 };
+guint _gtk_plug_signals[LAST_SIGNAL] = { 0 };
 
 GType
@@ -138,5 +124,5 @@ gtk_plug_class_init (GtkPlugClass *class
   window_class->keys_changed = gtk_plug_keys_changed;
 
-  plug_signals[EMBEDDED] =
+  _gtk_plug_signals[EMBEDDED] =
     g_signal_new ("embedded",
 		  G_OBJECT_CLASS_TYPE (class),
@@ -167,5 +153,5 @@ gtk_plug_set_is_child (GtkPlug  *plug,
     {
       if (plug->modality_window)
-	handle_modality_off (plug);
+	_gtk_plug_handle_modality_off (plug);
 
       if (plug->modality_group)
@@ -244,6 +230,6 @@ _gtk_plug_add_to_socket (GtkPlug   *plug
 }
 
-static void
-send_delete_event (GtkWidget *widget)
+void
+_gtk_plug_send_delete_event (GtkWidget *widget)
 {
   GdkEvent *event = gdk_event_new (GDK_DELETE);
@@ -315,5 +301,5 @@ _gtk_plug_remove_from_socket (GtkPlug   
     gtk_widget_destroy (GTK_WIDGET (socket));
 
-  send_delete_event (widget);
+  _gtk_plug_send_delete_event (widget);
 
   g_object_unref (plug);
@@ -371,4 +357,5 @@ gtk_plug_construct_for_display (GtkPlug 
       if (user_data)
 	{
+	  fprintf (stderr, "%s: got user data for %p: %p\n", __FUNCTION__, plug->socket_window, user_data);
 	  if (GTK_IS_SOCKET (user_data))
 	    _gtk_plug_add_to_socket (plug, user_data);
@@ -381,5 +368,5 @@ gtk_plug_construct_for_display (GtkPlug 
 
       if (plug->socket_window)
-	g_signal_emit (plug, plug_signals[EMBEDDED], 0);
+	g_signal_emit (plug, _gtk_plug_signals[EMBEDDED], 0);
     }
 }
@@ -423,25 +410,4 @@ gtk_plug_new_for_display (GdkDisplay	  *
 }
 
-/**
- * gtk_plug_get_id:
- * @plug: a #GtkPlug.
- * 
- * Gets the window ID of a #GtkPlug widget, which can then
- * be used to embed this window inside another window, for
- * instance with gtk_socket_add_id().
- * 
- * Return value: the window ID for the plug
- **/
-GdkNativeWindow
-gtk_plug_get_id (GtkPlug *plug)
-{
-  g_return_val_if_fail (GTK_IS_PLUG (plug), 0);
-
-  if (!GTK_WIDGET_REALIZED (plug))
-    gtk_widget_realize (GTK_WIDGET (plug));
-
-  return GDK_WINDOW_XWINDOW (GTK_WIDGET (plug)->window);
-}
-
 static void
 gtk_plug_finalize (GObject *object)
@@ -470,4 +436,5 @@ gtk_plug_unrealize (GtkWidget *widget)
     {
       gdk_window_set_user_data (plug->socket_window, NULL);
+      fprintf (stderr,"%s: set user data for %p: NULL\n", __FUNCTION__, plug->socket_window);
       g_object_unref (plug->socket_window);
       plug->socket_window = NULL;
@@ -477,5 +444,5 @@ gtk_plug_unrealize (GtkWidget *widget)
     {
       if (plug->modality_window)
-	handle_modality_off (plug);
+	_gtk_plug_handle_modality_off (plug);
 
       gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug));
@@ -548,10 +515,10 @@ gtk_plug_realize (GtkWidget *widget)
 	}
       
-      gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget);
+      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);
+      _gtk_plug_realize_toplevel (widget->window, plug->socket_window);
     }
   else
@@ -560,4 +527,5 @@ gtk_plug_realize (GtkWidget *widget)
   
   gdk_window_set_user_data (widget->window, window);
+  fprintf (stderr, "%s: set user data for %p to %p\n", __FUNCTION__, widget->window, window);
 
   widget->style = gtk_style_attach (widget->style, widget->window);
@@ -593,7 +561,9 @@ static void
 gtk_plug_map (GtkWidget *widget)
 {
+  fprintf (stderr, "gtk_plug_map\n"); fflush (stderr);
   if (GTK_WIDGET_TOPLEVEL (widget))
     {
       GtkBin *bin = GTK_BIN (widget);
+      GtkPlug *plug = GTK_PLUG (widget);
       
       GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
@@ -604,5 +574,5 @@ gtk_plug_map (GtkWidget *widget)
 	gtk_widget_map (bin->child);
 
-      xembed_set_info (widget->window, XEMBED_MAPPED);
+      _gtk_plug_map_toplevel (widget->window, plug->socket_window);
       
       gdk_synthesize_window_state (widget->window,
@@ -619,8 +589,11 @@ gtk_plug_unmap (GtkWidget *widget)
   if (GTK_WIDGET_TOPLEVEL (widget))
     {
+      GtkPlug *plug = GTK_PLUG (widget);
+
       GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
 
       gdk_window_hide (widget->window);
-      xembed_set_info (widget->window, 0);
+
+      _gtk_plug_unmap_toplevel (widget->window, plug->socket_window);
       
       gdk_synthesize_window_state (widget->window,
@@ -698,16 +671,7 @@ gtk_plug_set_focus (GtkWindow *window,
 
   if (focus && !window->has_toplevel_focus)
-    {
-      _gtk_xembed_send_message (plug->socket_window,
-				XEMBED_REQUEST_FOCUS, 0, 0, 0);
-    }
+    _gtk_plug_set_focus (plug->socket_window);
 }
 
-typedef struct
-{
-  guint			 accelerator_key;
-  GdkModifierType	 accelerator_mods;
-} GrabbedKey;
-
 static guint
 grabbed_key_hash (gconstpointer a)
@@ -742,17 +706,21 @@ add_grabbed_key (gpointer key, gpointer 
       !g_hash_table_lookup (plug->grabbed_keys, grabbed_key))
     {
-      _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0, 
-				grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
+      _gtk_plug_add_grabbed_key (plug->socket_window,
+				 grabbed_key->accelerator_key,
+				 grabbed_key->accelerator_mods);
     }
 }
 
-static void
-add_grabbed_key_always (gpointer key, gpointer val, gpointer data)
+void
+_gtk_plug_add_grabbed_key_always (gpointer key,
+				  gpointer val,
+				  gpointer data)
 {
   GrabbedKey *grabbed_key = key;
   GtkPlug *plug = data;
 
-  _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0, 
-			    grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
+  _gtk_plug_add_grabbed_key (plug->socket_window,
+			     grabbed_key->accelerator_key,
+			     grabbed_key->accelerator_mods);
 }
 
@@ -766,6 +734,7 @@ remove_grabbed_key (gpointer key, gpoint
       !g_hash_table_lookup (plug->grabbed_keys, grabbed_key))
     {
-      _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_UNGRAB_KEY, 0, 
-				grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
+      _gtk_plug_remove_grabbed_key (plug->socket_window, 
+				    grabbed_key->accelerator_key,
+				    grabbed_key->accelerator_mods);
     }
 }
@@ -810,27 +779,4 @@ gtk_plug_keys_changed (GtkWindow *window
 }
 
-static void
-focus_to_parent (GtkPlug          *plug,
-		 GtkDirectionType  direction)
-{
-  XEmbedMessageType message = XEMBED_FOCUS_PREV; /* Quiet GCC */
-  
-  switch (direction)
-    {
-    case GTK_DIR_UP:
-    case GTK_DIR_LEFT:
-    case GTK_DIR_TAB_BACKWARD:
-      message = XEMBED_FOCUS_PREV;
-      break;
-    case GTK_DIR_DOWN:
-    case GTK_DIR_RIGHT:
-    case GTK_DIR_TAB_FORWARD:
-      message = XEMBED_FOCUS_NEXT;
-      break;
-    }
-  
-  _gtk_xembed_send_focus_message (plug->socket_window, message, 0);
-}
-
 static gboolean
 gtk_plug_focus (GtkWidget        *widget,
@@ -872,5 +818,5 @@ gtk_plug_focus (GtkWidget        *widget
 
   if (!GTK_CONTAINER (window)->focus_child)
-    focus_to_parent (plug, direction);
+    _gtk_plug_focus_to_parent (plug->socket_window, direction);
 
   return FALSE;
@@ -886,29 +832,8 @@ gtk_plug_check_resize (GtkContainer *con
 }
 
-static void
-focus_first_last (GtkPlug          *plug,
-		  GtkDirectionType  direction)
-{
-  GtkWindow *window = GTK_WINDOW (plug);
-  GtkWidget *parent;
-
-  if (window->focus_widget)
-    {
-      parent = window->focus_widget->parent;
-      while (parent)
-	{
-	  gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
-	  parent = GTK_WIDGET (parent)->parent;
-	}
-      
-      gtk_window_set_focus (GTK_WINDOW (plug), NULL);
-    }
-
-  gtk_widget_child_focus (GTK_WIDGET (plug), direction);
-}
-
-static void
-handle_modality_on (GtkPlug *plug)
+void
+_gtk_plug_handle_modality_on (GtkPlug *plug)
 {
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
   if (!plug->modality_window)
     {
@@ -922,6 +847,6 @@ handle_modality_on (GtkPlug *plug)
 }
 
-static void
-handle_modality_off (GtkPlug *plug)
+void
+_gtk_plug_handle_modality_off (GtkPlug *plug)
 {
   if (plug->modality_window)
@@ -932,209 +857,26 @@ handle_modality_off (GtkPlug *plug)
 }
 
-static void
-xembed_set_info (GdkWindow     *window,
-		 unsigned long  flags)
-{
-  GdkDisplay *display = gdk_drawable_get_display (window);
-  unsigned long buffer[2];
-
-  Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
-
-  buffer[0] = GTK_XEMBED_PROTOCOL_VERSION;
-  buffer[1] = flags;
-
-  XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
-		   GDK_WINDOW_XWINDOW (window),
-		   xembed_info_atom, xembed_info_atom, 32,
-		   PropModeReplace,
-		   (unsigned char *)buffer, 2);
-}
-
-static void
-handle_xembed_message (GtkPlug           *plug,
-		       XEmbedMessageType  message,
-		       glong              detail,
-		       glong              data1,
-		       glong              data2,
-		       guint32            time)
+void
+_gtk_plug_focus_first_last (GtkPlug          *plug,
+			    GtkDirectionType  direction)
 {
   GtkWindow *window = GTK_WINDOW (plug);
+  GtkWidget *parent;
 
-  GTK_NOTE (PLUGSOCKET,
-	    g_message ("GtkPlug: Message of type %d received", message));
-  
-  switch (message)
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  if (window->focus_widget)
     {
-    case XEMBED_EMBEDDED_NOTIFY:
-      break;
-    case XEMBED_WINDOW_ACTIVATE:
-      _gtk_window_set_is_active (window, TRUE);
-      break;
-    case XEMBED_WINDOW_DEACTIVATE:
-      _gtk_window_set_is_active (window, FALSE);
-      break;
-      
-    case XEMBED_MODALITY_ON:
-      handle_modality_on (plug);
-      break;
-    case XEMBED_MODALITY_OFF:
-      handle_modality_off (plug);
-      break;
-
-    case XEMBED_FOCUS_IN:
-      _gtk_window_set_has_toplevel_focus (window, TRUE);
-      switch (detail)
+      parent = window->focus_widget->parent;
+      while (parent)
 	{
-	case XEMBED_FOCUS_FIRST:
-	  focus_first_last (plug, GTK_DIR_TAB_FORWARD);
-	  break;
-	case XEMBED_FOCUS_LAST:
-	  focus_first_last (plug, GTK_DIR_TAB_BACKWARD);
-	  break;
-	case XEMBED_FOCUS_CURRENT:
-	  break;
+	  gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
+	  parent = GTK_WIDGET (parent)->parent;
 	}
-      break;
-
-    case XEMBED_FOCUS_OUT:
-      _gtk_window_set_has_toplevel_focus (window, FALSE);
-      break;
-      
-    case XEMBED_GRAB_KEY:
-    case XEMBED_UNGRAB_KEY:
-    case XEMBED_GTK_GRAB_KEY:
-    case XEMBED_GTK_UNGRAB_KEY:
-    case XEMBED_REQUEST_FOCUS:
-    case XEMBED_FOCUS_NEXT:
-    case XEMBED_FOCUS_PREV:
-      g_warning ("GtkPlug: Invalid _XEMBED message of type %d received", message);
-      break;
       
-    default:
-      GTK_NOTE(PLUGSOCKET,
-	       g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %d", message));
-      break;
+      gtk_window_set_focus (GTK_WINDOW (plug), NULL);
     }
-}
-
-static GdkFilterReturn
-gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
-{
-  GdkScreen *screen = gdk_drawable_get_screen (event->any.window);
-  GdkDisplay *display = gdk_screen_get_display (screen);
-  GtkPlug *plug = GTK_PLUG (data);
-  XEvent *xevent = (XEvent *)gdk_xevent;
-
-  GdkFilterReturn return_val;
-  
-  return_val = GDK_FILTER_CONTINUE;
 
-  switch (xevent->type)
-    {
-    case ClientMessage:
-      if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"))
-	{
-	  _gtk_xembed_push_message (xevent);
-	  handle_xembed_message (plug,
-				 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_xembed_pop_message ();
-				 
-	  return GDK_FILTER_REMOVE;
-	}
-      else if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
-	{
-	  /* We filter these out because we take being reparented back to the
-	   * root window as the reliable end of the embedding protocol
-	   */
-
-	  return GDK_FILTER_REMOVE;
-	}
-      break;
-    case ReparentNotify:
-      {
-	XReparentEvent *xre = &xevent->xreparent;
-	gboolean was_embedded = plug->socket_window != NULL;
+  gtk_widget_child_focus (GTK_WIDGET (plug), direction);
+}
 
-	return_val = GDK_FILTER_REMOVE;
-	
-	g_object_ref (plug);
-	
-	if (was_embedded)
-	  {
-	    /* End of embedding protocol for previous socket */
-	    
-	    /* FIXME: race if we remove from another socket and
-	     * then add to a local window before we get notification
-	     * Probably need check in _gtk_plug_add_to_socket
-	     */
-	    
-	    if (xre->parent != GDK_WINDOW_XWINDOW (plug->socket_window))
-	      {
-		GtkWidget *widget = GTK_WIDGET (plug);
-
-		gdk_window_set_user_data (plug->socket_window, NULL);
-		g_object_unref (plug->socket_window);
-		plug->socket_window = NULL;
-
-		/* Emit a delete window, as if the user attempted
-		 * to close the toplevel. Simple as to how we
-		 * handle WM_DELETE_WINDOW, if it isn't handled
-		 * we destroy the widget. BUt only do this if
-		 * we are being reparented to the root window.
-		 * Moving from one embedder to another should
-		 * be invisible to the app.
-		 */
-
-		if (xre->parent == GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)))
-		  send_delete_event (widget);
-	      }
-	    else
-	      goto done;
-	  }
-
-	if (xre->parent != GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)))
-	  {
-	    /* Start of embedding protocol */
-
-	    plug->socket_window = gdk_window_lookup_for_display (display, xre->parent);
-	    if (plug->socket_window)
-	      {
-		gpointer user_data = NULL;
-		gdk_window_get_user_data (plug->socket_window, &user_data);
-
-		if (user_data)
-		  {
-		    g_warning (G_STRLOC "Plug reparented unexpectedly into window in the same process");
-		    plug->socket_window = NULL;
-		    break;
-		  }
-
-		g_object_ref (plug->socket_window);
-	      }
-	    else
-	      {
-		plug->socket_window = gdk_window_foreign_new_for_display (display, xre->parent);
-		if (!plug->socket_window) /* Already gone */
-		  break;
-	      }
-
-	    if (plug->grabbed_keys)
-	      g_hash_table_foreach (plug->grabbed_keys, add_grabbed_key_always, plug);
-
-	    if (!was_embedded)
-	      g_signal_emit (plug, plug_signals[EMBEDDED], 0);
-	  }
-
-      done:
-	g_object_unref (plug);
-	
-	break;
-      }
-    }
 
-  return GDK_FILTER_CONTINUE;
-}
Index: gtk/gtkplugprivate.h
===================================================================
RCS file: gtk/gtkplugprivate.h
diff -N gtk/gtkplugprivate.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkplugprivate.h	17 Mar 2005 00:36:13 -0000
@@ -0,0 +1,73 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GTK_PLUG_PRIVATE_H__
+#define __GTK_PLUG_PRIVATE_H__
+
+enum {
+  EMBEDDED,
+  LAST_SIGNAL
+}; 
+
+typedef struct
+{
+  guint			 accelerator_key;
+  GdkModifierType	 accelerator_mods;
+} GrabbedKey;
+
+guint _gtk_plug_signals[LAST_SIGNAL];
+
+/* In gtkplug.c: */
+void _gtk_plug_send_delete_event      (GtkWidget        *widget);
+void _gtk_plug_add_grabbed_key_always (gpointer          key,
+				       gpointer          val,
+				       gpointer          data);
+void _gtk_plug_focus_first_last       (GtkPlug          *plug,
+				       GtkDirectionType  direction);
+void _gtk_plug_handle_modality_on     (GtkPlug *plug);
+void _gtk_plug_handle_modality_off    (GtkPlug *plug);
+
+/* In backend-specific file (gtkplug-x11.c or gtkplug-win32.c): */
+void _gtk_plug_realize_toplevel   (GdkWindow 	   *plug_window,
+				   GdkWindow       *socket_window);
+void _gtk_plug_map_toplevel       (GdkWindow 	   *plug_window,
+				   GdkWindow       *socket_window);
+void _gtk_plug_unmap_toplevel     (GdkWindow 	   *plug_window,
+				   GdkWindow       *socket_window);
+void _gtk_plug_set_focus          (GdkWindow 	   *socket_window);
+void _gtk_plug_add_grabbed_key    (GdkWindow       *socket_window,
+				   guint            accelerator_key,
+				   GdkModifierType  accelerator_mods);
+void _gtk_plug_remove_grabbed_key (GdkWindow       *socket_window,
+				   guint            accelerator_key,
+				   GdkModifierType  accelerator_mods);
+void _gtk_plug_focus_to_parent    (GdkWindow       *socket_window,
+				   GtkDirectionType direction);
+
+GdkFilterReturn _gtk_plug_filter_func (GdkXEvent *gdk_xevent,
+				       GdkEvent  *event,
+				       gpointer   data);
+
+#endif /* __GTK_PLUG_PRIVATE_H__ */
Index: gtk/gtksocket-win32.c
===================================================================
RCS file: gtk/gtksocket-win32.c
diff -N gtk/gtksocket-win32.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtksocket-win32.c	17 Mar 2005 00:36:13 -0000
@@ -0,0 +1,454 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 2005 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* By Tor Lillqvist <tml@novell.com> 2005 */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2005.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "gtkwindow.h"
+#include "gtkplug.h"
+#include "gtkprivate.h"
+#include "gtksocket.h"
+#include "gtksocketprivate.h"
+
+#include "win32/gdkwin32.h"
+
+#include "gtkwin32embed.h"
+
+GdkNativeWindow
+gtk_socket_get_id (GtkSocket *socket)
+{
+  g_return_val_if_fail (GTK_IS_SOCKET (socket), 0);
+  g_return_val_if_fail (GTK_WIDGET_ANCHORED (socket), 0);
+
+  if (!GTK_WIDGET_REALIZED (socket))
+    gtk_widget_realize (GTK_WIDGET (socket));
+
+  return (GdkNativeWindow) GDK_WINDOW_HWND (GTK_WIDGET (socket)->window);
+}
+
+void
+_gtk_socket_realize_window (GdkWindow *window)
+{
+  /* ??? */
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+}
+
+void
+_gtk_socket_end_embeddding_toplevel (GtkWidget *toplevel,
+				     GdkWindow *plug_window)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), 
+				  (guint) GDK_WINDOW_HWND (plug_window));
+}
+
+void
+_gtk_socket_size_request (GtkSocket *socket)
+{
+  RECT rect;
+
+  socket->request_width = 1;
+  socket->request_height = 1;
+  
+  if (GetClientRect (GDK_WINDOW_HWND (socket->plug_window), &rect))
+    {
+      socket->request_width = rect.right;
+      socket->request_height = rect.bottom;
+    }
+  socket->have_size = TRUE;
+
+  fprintf (stderr, "%s: %p: %dx%d\n",
+	   __FUNCTION__,
+	   socket->plug_window,
+	   socket->request_width, socket->request_height);
+  fflush (stderr);
+}
+
+void
+_gtk_socket_send_key_event (GtkSocket *socket,
+			    GdkScreen *screen,
+			    GdkEvent  *gdk_event,
+			    gboolean   mask_key_presses)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+
+  PostMessage (GDK_WINDOW_HWND (socket->plug_window),
+	       (gdk_event->type == GDK_KEY_PRESS ? WM_KEYDOWN : WM_KEYUP),
+	       gdk_event->key.hardware_keycode, 0);
+}
+
+void
+_gtk_socket_focus_change (GdkWindow *plug_window,
+			  gboolean   focus_in)
+{
+  fprintf (stderr, "%s: %s\n", __FUNCTION__, (focus_in ? "IN" : "OUT")); fflush (stderr);
+  if (focus_in)
+    _gtk_win32_embed_send_focus_message (plug_window, GTK_WIN32_EMBED_FOCUS_IN,
+					 GTK_WIN32_EMBED_FOCUS_CURRENT);
+  else
+    _gtk_win32_embed_send (plug_window, GTK_WIN32_EMBED_FOCUS_OUT,
+			   0, 0);
+}
+
+void
+_gtk_socket_active_change (GdkWindow *plug_window,
+			   gboolean   active)
+{
+  fprintf (stderr, "%s: %s\n", __FUNCTION__, (active ? "YES" : "NO")); fflush (stderr);
+  _gtk_win32_embed_send (plug_window, GTK_WIN32_EMBED_WINDOW_ACTIVATE,
+			 active, 0);
+}
+
+void
+_gtk_socket_modality_change (GdkWindow *plug_window,
+			     gboolean   modality)
+{
+  fprintf (stderr, "%s: %s\n", __FUNCTION__, (modality ? "YES" : "NO")); fflush (stderr);
+
+  _gtk_win32_embed_send (plug_window,
+			 (modality ? GTK_WIN32_EMBED_MODALITY_ON : GTK_WIN32_EMBED_MODALITY_OFF),
+			 0, 0);
+}
+
+void
+_gtk_socket_focus (GdkWindow       *plug_window,
+		   GtkDirectionType direction)
+{
+  int detail = -1;
+
+#define CASE(x) direction == GTK_DIR_##x ? #x
+  fprintf (stderr, "%s: %s\n", __FUNCTION__,
+	   (CASE (UP) :
+	    (CASE (LEFT) :
+	     (CASE (TAB_BACKWARD) :
+	      (CASE (DOWN) :
+	       (CASE (RIGHT) :
+		(CASE (TAB_FORWARD) : "???")))))));
+  fflush (stderr);
+#undef CASE
+
+  switch (direction)
+    {
+    case GTK_DIR_UP:
+    case GTK_DIR_LEFT:
+    case GTK_DIR_TAB_BACKWARD:
+      detail = GTK_WIN32_EMBED_FOCUS_LAST;
+      break;
+    case GTK_DIR_DOWN:
+    case GTK_DIR_RIGHT:
+    case GTK_DIR_TAB_FORWARD:
+      detail = GTK_WIN32_EMBED_FOCUS_FIRST;
+      break;
+    }
+  
+  _gtk_win32_embed_send_focus_message (plug_window, GTK_WIN32_EMBED_FOCUS_IN,
+				       detail);
+}
+
+void
+_gtk_socket_send_configure_event (GtkSocket *socket)
+{
+  gint x, y;
+
+  gdk_window_get_origin (socket->plug_window, &x, &y);
+
+  fprintf (stderr, "%s: %p %dx%d@%+d%+d\n",
+	   __FUNCTION__,
+	   GDK_WINDOW_HWND (socket->plug_window),
+	   GTK_WIDGET(socket)->allocation.width,
+	   GTK_WIDGET(socket)->allocation.height,
+	   x, y);
+  fflush (stderr);
+
+  PostMessage (GDK_WINDOW_HWND (socket->plug_window),
+	       WM_SIZE, SIZE_RESTORED,
+	       (GTK_WIDGET(socket)->allocation.width & 0xFFFF) +
+	       (GTK_WIDGET(socket)->allocation.height << 16));
+
+  PostMessage (GDK_WINDOW_HWND (socket->plug_window),
+	       WM_MOVE, SIZE_RESTORED,
+	       (x & 0xFFFF) + (y << 16));
+}
+
+void
+_gtk_socket_select_plug_window_input (GdkDisplay *display,
+				      GdkWindow  *plug_window,
+				      GdkWindow  *socket_window)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+
+  _gtk_win32_embed_send (plug_window, GTK_WIN32_EMBED_REQUEST_EVENTS,
+			 (gint) GDK_WINDOW_HWND (socket_window), 0);
+}
+
+void
+_gtk_socket_embed_get_info (GtkSocket *socket)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+
+  socket->is_mapped = TRUE;	/* XXX */
+}
+
+void
+_gtk_socket_embed_notify (GtkSocket *socket)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+  /* Nothing needed */
+}
+
+gboolean
+_gtk_socket_embed_get_focus_wrapped (void)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+
+  return _gtk_win32_embed_get_focus_wrapped ();
+  return FALSE;
+}
+
+void
+_gtk_socket_embed_set_focus_wrapped (void)
+{
+  fprintf (stderr, "%s\n", __FUNCTION__); fflush (stderr);
+
+  _gtk_win32_embed_set_focus_wrapped ();
+}
+
+GdkFilterReturn
+_gtk_socket_filter_func (GdkXEvent *gdk_xevent,
+			 GdkEvent  *event,
+			 gpointer   data)
+{
+  GtkSocket *socket;
+  GtkWidget *widget;
+  MSG *msg;
+  GdkFilterReturn return_val;
+
+  socket = GTK_SOCKET (data);
+
+  return_val = GDK_FILTER_CONTINUE;
+
+  if (socket->plug_widget)
+    return return_val;
+
+  fprintf (stderr, "%s: ", __FUNCTION__); fflush (stderr);
+
+  widget = GTK_WIDGET (socket);
+  msg = (MSG *) gdk_xevent;
+
+  switch (msg->message)
+    {
+#if 0
+    case WM_CREATE:
+      if (!socket->plug_window)
+	{
+	  LPCREATESTRUCT lpcs = (LPCREATESTRUCT)msg->lParam;
+	    
+	  _gtk_socket_add_window (socket, (UINT)msg->hwnd, FALSE);
+
+	  gdk_window_move_resize(socket->plug_window,
+				 0, 0,
+				 widget->allocation.width, 
+				 widget->allocation.height);
+	  gdk_flush ();
+	
+	  socket->request_width = lpcs->cx;
+	  socket->request_height = lpcs->cy;
+	  socket->have_size = TRUE;
+
+	  GTK_NOTE(PLUGSOCKET,
+		   g_printerr ("GtkSocket - window created with size: %dx%d\n",
+			       socket->request_width,
+			       socket->request_height));
+	}
+      
+      return_val = GDK_FILTER_REMOVE;
+      break;
+
+    case WM_SIZE:
+      goto move;
+    case WM_MOVE:
+    move:
+      if (!socket->plug_window)
+	_gtk_socket_add_window (socket, (UINT)msg->hwnd, FALSE);
+	
+      if (socket->plug_window &&
+	  msg->hwnd == GDK_WINDOW_HWND (socket->plug_window))
+	{
+	  GtkSocketPrivate *private = _gtk_socket_get_private (socket);
+
+	  if (msg->message == WM_SIZE)
+	    {
+	      socket->request_width = LOWORD(msg->lParam);
+	      socket->request_height = HIWORD(msg->lParam);
+	      socket->have_size = TRUE;
+		
+	      GTK_NOTE (PLUGSOCKET,
+			g_printerr ("GtkSocket - configure request: %d %d\n",
+				    socket->request_width,
+				    socket->request_height));
+	      
+	      private->resize_count++;
+	      gtk_widget_queue_resize (widget);
+	    }
+	  else if (msg->message == WM_MOVE)
+	    {
+	      /*
+	       * xPos = (int)LOWORD(lParam);
+	       * yPos = (int)HIWORD(lParam);
+	       */
+	      /* XXX: X11 version does almost nothing, is it enough ? */
+	      _gtk_socket_send_configure_event (socket);
+	    }
+	  /* Ignore stacking requests. */
+	    
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      break;
+
+    case WM_DESTROY:
+      if (socket->plug_window &&
+	  (msg->hwnd == GDK_WINDOW_HWND (socket->plug_window)))
+	{
+	  GtkWidget *toplevel;
+
+	  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
+	  if (toplevel && GTK_IS_WINDOW (toplevel))
+	    gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), (UINT)msg->hwnd);
+	    
+	  gdk_window_destroy_notify (socket->plug_window);
+	  gtk_widget_destroy (widget);
+
+	  socket->plug_window = NULL;
+	    
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      break;
+
+    case WM_SETFOCUS:
+      _gtk_socket_claim_focus (socket, FALSE);
+      return_val = GDK_FILTER_REMOVE;
+      break;
+
+    case WM_KILLFOCUS:
+      return_val = GDK_FILTER_REMOVE;
+      break;
+
+    case WM_SHOWWINDOW:
+      if (!socket->plug_window)
+	_gtk_socket_add_window (socket, (UINT)msg->hwnd, FALSE);
+	
+      if (msg->wParam &&
+          msg->lParam != 0)	/* Avoid infinite recursion */
+	{
+	  gdk_window_show (socket->plug_window);
+
+	  return_val = GDK_FILTER_REMOVE;
+	}
+	break;
+#endif
+    case WM_PARENTNOTIFY:
+      fprintf (stderr, "WM_PARENTNOTIFY: ");
+      if (LOWORD (msg->wParam) == WM_CREATE && !socket->plug_window)
+	{
+	  _gtk_socket_add_window (socket, msg->lParam, FALSE);
+
+	  if (socket->plug_window)
+	    GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window created"));
+	
+	  return_val = GDK_FILTER_REMOVE;
+	}
+	break;
+
+    default:
+      if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_EVENT_PLUG_MAPPED))
+	{
+	  gboolean was_mapped = socket->is_mapped;
+	  gboolean is_mapped = msg->wParam != 0;
+
+	  fprintf (stderr, "EVENT_PLUG_MAPPED: was_mapped:%d is_mapped:%d ", was_mapped, is_mapped);
+	  
+	  if (was_mapped != is_mapped)
+	    {
+	      if (is_mapped)
+		_gtk_socket_map_request (socket);
+	      else
+		{
+		  gdk_window_show (socket->plug_window);
+		  _gtk_socket_unmap_notify (socket);
+		}
+	    }
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_REQUEST_FOCUS))
+	{
+	  fprintf (stderr, "REQUEST_FOCUS: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_socket_claim_focus (socket, TRUE);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_NEXT))
+	{
+	  fprintf (stderr, "FOCUS_NEXT: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_socket_advance_toplevel_focus (socket, GTK_DIR_TAB_FORWARD);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_PREV))
+	{
+	  fprintf (stderr, "FOCUS_PREV: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_socket_advance_toplevel_focus (socket, GTK_DIR_TAB_BACKWARD);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_GRAB_KEY))
+	{
+	  fprintf (stderr, "GRAB_KEY: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_socket_add_grabbed_key (socket, msg->wParam, msg->lParam);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      else if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_UNGRAB_KEY))
+	{
+	  fprintf (stderr, "GRAB_KEY: ");
+	  _gtk_win32_embed_push_message (msg);
+	  _gtk_socket_remove_grabbed_key (socket, msg->wParam, msg->lParam);
+	  _gtk_win32_embed_pop_message ();
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      break;
+    }
+
+  fprintf (stderr, "\n"); fflush (stderr);
+
+  return return_val;
+}
+
Index: gtk/gtksocket-x11.c
===================================================================
RCS file: gtk/gtksocket-x11.c
diff -N gtk/gtksocket-x11.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtksocket-x11.c	17 Mar 2005 00:36:14 -0000
@@ -0,0 +1,679 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* By Owen Taylor <otaylor@gtk.org>              98/4/4 */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "gdk/gdkkeysyms.h"
+#include "gtkalias.h"
+#include "gtkmain.h"
+#include "gtkmarshalers.h"
+#include "gtkwindow.h"
+#include "gtkplug.h"
+#include "gtkprivate.h"
+#include "gtksocket.h"
+#include "gtksocketprivate.h"
+#include "gtkdnd.h"
+
+#include "x11/gdkx.h"
+
+#include "gtkxembed.h"
+
+static gboolean xembed_get_info     (GdkWindow     *gdk_window,
+				     unsigned long *version,
+				     unsigned long *flags);
+
+/* From Tk */
+#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
+
+/**
+ * gtk_socket_get_id:
+ * @socket_: a #GtkSocket.
+ * 
+ * Gets the window ID of a #GtkSocket widget, which can then
+ * be used to create a client embedded inside the socket, for
+ * instance with gtk_plug_new(). 
+ *
+ * The #GtkSocket must have already be added into a toplevel window 
+ * before you can make this call.
+ * 
+ * Return value: the window ID for the socket
+ **/
+GdkNativeWindow
+gtk_socket_get_id (GtkSocket *socket)
+{
+  g_return_val_if_fail (GTK_IS_SOCKET (socket), 0);
+  g_return_val_if_fail (GTK_WIDGET_ANCHORED (socket), 0);
+
+  if (!GTK_WIDGET_REALIZED (socket))
+    gtk_widget_realize (GTK_WIDGET (socket));
+
+  return GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window);
+}
+
+void
+_gtk_socket_realize_window (GdkWindow *window)
+{
+  XWindowAttributes xattrs;
+
+  XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
+			GDK_WINDOW_XWINDOW (window),
+			&xattrs);
+
+  XSelectInput (GDK_WINDOW_XDISPLAY (window),
+		GDK_WINDOW_XWINDOW (window), 
+		xattrs.your_event_mask | 
+		SubstructureNotifyMask | SubstructureRedirectMask);
+}
+
+void
+_gtk_socket_end_embeddding_toplevel (GtkWidget *toplevel,
+				     GdkWindow *plug_window)
+{
+  gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), 
+				  GDK_WINDOW_XWINDOW (plug_window));
+}
+
+void
+_gtk_socket_size_request (GtkSocket *socket)
+{
+  XSizeHints hints;
+  long supplied;
+	  
+  gdk_error_trap_push ();
+
+  socket->request_width = 1;
+  socket->request_height = 1;
+	  
+  if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window),
+			 GDK_WINDOW_XWINDOW (socket->plug_window),
+			 &hints, &supplied))
+    {
+      if (hints.flags & PMinSize)
+	{
+	  fprintf (stderr, "%s: got PMinSize: %dx%d\n", __FUNCTION__, hints.min_width, hints.min_height); fflush (stderr);
+	  socket->request_width = hints.min_width;
+	  socket->request_height = hints.min_height;
+	}
+      else if (hints.flags & PBaseSize)
+	{
+	  fprintf (stderr, "%s: got PBaseSize: %dx%d\n", __FUNCTION__, hints.base_width, hints.base_height); fflush (stderr);
+	  socket->request_width = hints.base_width;
+	  socket->request_height = hints.base_height;
+	}
+    }
+  socket->have_size = TRUE;
+  
+  gdk_error_trap_pop ();
+}
+
+void
+_gtk_socket_send_key_event (GtkSocket *socket,
+			    GdkScreen *screen,
+			    GdkEvent  *gdk_event,
+			    gboolean   mask_key_presses)
+{
+  XEvent xevent;
+
+  xevent.xkey.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
+  xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
+  xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+  xevent.xkey.subwindow = None;
+  xevent.xkey.time = gdk_event->key.time;
+  xevent.xkey.x = 0;
+  xevent.xkey.y = 0;
+  xevent.xkey.x_root = 0;
+  xevent.xkey.y_root = 0;
+  xevent.xkey.state = gdk_event->key.state;
+  xevent.xkey.keycode = gdk_event->key.hardware_keycode;
+  xevent.xkey.same_screen = True;/* FIXME ? */
+
+  gdk_error_trap_push ();
+  XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
+	      GDK_WINDOW_XWINDOW (socket->plug_window),
+	      False,
+	      (mask_key_presses ? KeyPressMask : NoEventMask),
+	      &xevent);
+  gdk_display_sync (gdk_screen_get_display (screen));
+  gdk_error_trap_pop ();
+}
+
+void
+_gtk_socket_focus_change (GdkWindow *plug_window,
+			  gboolean   focus_in)
+{
+  fprintf (stderr, "%s: %s\n", __FUNCTION__, (focus_in ? "IN" : "OUT")); fflush (stderr);
+  if (focus_in)
+    _gtk_xembed_send_focus_message (plug_window,
+				    XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
+  else
+    _gtk_xembed_send_message (plug_window,
+			      XEMBED_FOCUS_OUT, 0, 0, 0);
+}
+
+void
+_gtk_socket_active_change (GdkWindow *plug_window,
+			   gboolean   active)
+{
+  fprintf (stderr, "%s: %s\n", __FUNCTION__, (active ? "YES" : "NO")); fflush (stderr);
+  _gtk_xembed_send_message (plug_window,
+			    active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
+			    0, 0, 0);
+}
+
+void
+_gtk_socket_modality_change (GdkWindow *plug_window,
+			     gboolean   modality)
+{
+  fprintf (stderr, "%s: %s\n", __FUNCTION__, (modality ? "YES" : "NO")); fflush (stderr);
+  _gtk_xembed_send_message (plug_window,
+			    modality ? XEMBED_MODALITY_ON : XEMBED_MODALITY_OFF,
+			    0, 0, 0);
+}
+
+void
+_gtk_socket_focus (GdkWindow       *plug_window,
+		   GtkDirectionType direction)
+{
+  gint detail = -1;
+
+  switch (direction)
+    {
+    case GTK_DIR_UP:
+    case GTK_DIR_LEFT:
+    case GTK_DIR_TAB_BACKWARD:
+      detail = XEMBED_FOCUS_LAST;
+      break;
+    case GTK_DIR_DOWN:
+    case GTK_DIR_RIGHT:
+    case GTK_DIR_TAB_FORWARD:
+      detail = XEMBED_FOCUS_FIRST;
+      break;
+    }
+  
+  _gtk_xembed_send_focus_message (plug_window,
+				  XEMBED_FOCUS_IN, detail);
+}
+
+void
+_gtk_socket_send_configure_event (GtkSocket *socket)
+{
+  XEvent event;
+  gint x, y;
+
+  g_return_if_fail (socket->plug_window != NULL);
+
+  event.xconfigure.type = ConfigureNotify;
+
+  event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
+  event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
+
+  /* The ICCCM says that synthetic events should have root relative
+   * coordinates. We still aren't really ICCCM compliant, since
+   * we don't send events when the real toplevel is moved.
+   */
+  gdk_error_trap_push ();
+  gdk_window_get_origin (socket->plug_window, &x, &y);
+  gdk_error_trap_pop ();
+			 
+  event.xconfigure.x = x;
+  event.xconfigure.y = y;
+  event.xconfigure.width = GTK_WIDGET(socket)->allocation.width;
+  event.xconfigure.height = GTK_WIDGET(socket)->allocation.height;
+
+  event.xconfigure.border_width = 0;
+  event.xconfigure.above = None;
+  event.xconfigure.override_redirect = False;
+
+  gdk_error_trap_push ();
+  XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
+	      GDK_WINDOW_XWINDOW (socket->plug_window),
+	      False, NoEventMask, &event);
+  gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket)));
+  gdk_error_trap_pop ();
+}
+
+void
+_gtk_socket_select_plug_window_input (GdkDisplay *display,
+				      GdkWindow  *plug_window,
+				      GdkWindow  *socket_window)
+{
+  XSelectInput (GDK_DISPLAY_XDISPLAY (display),
+		GDK_WINDOW_XWINDOW (plug_window),
+		StructureNotifyMask | PropertyChangeMask);
+}
+
+void
+_gtk_socket_embed_get_info (GtkSocket *socket)
+{
+  unsigned long version;
+  unsigned long flags;
+
+  socket->xembed_version = -1;
+  if (xembed_get_info (socket->plug_window, &version, &flags))
+    {
+      fprintf (stderr, "xembed_get_info succeeded flags=%#x\n", flags);
+      socket->xembed_version = MIN (GTK_XEMBED_PROTOCOL_VERSION, version);
+      socket->is_mapped = (flags & XEMBED_MAPPED) != 0;
+    }
+  else
+    {
+      /* FIXME, we should probably actually check the state before we started */
+      fprintf (stderr, "xembed_get_info failed, setting is_mapped=TRUE\n");
+      socket->is_mapped = TRUE;
+    }
+}
+
+void
+_gtk_socket_embed_notify (GtkSocket *socket)
+{
+  _gtk_xembed_send_message (socket->plug_window,
+			    XEMBED_EMBEDDED_NOTIFY, 0,
+			    GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window),
+			    socket->xembed_version);
+}
+
+static gboolean
+xembed_get_info (GdkWindow     *window,
+		 unsigned long *version,
+		 unsigned long *flags)
+{
+  GdkDisplay *display = gdk_drawable_get_display (window);
+  Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
+  Atom type;
+  int format;
+  unsigned long nitems, bytes_after;
+  unsigned char *data;
+  unsigned long *data_long;
+  int status;
+  
+  gdk_error_trap_push();
+  status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+			       GDK_WINDOW_XWINDOW (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;
+}
+
+gboolean
+_gtk_socket_embed_get_focus_wrapped (void)
+{
+  return _gtk_xembed_get_focus_wrapped ();
+}
+
+void
+_gtk_socket_embed_set_focus_wrapped (void)
+{
+  _gtk_xembed_set_focus_wrapped ();
+}
+
+static void
+handle_xembed_message (GtkSocket        *socket,
+		       XEmbedMessageType message,
+		       glong             detail,
+		       glong             data1,
+		       glong             data2,
+		       guint32           time)
+{
+  GTK_NOTE (PLUGSOCKET,
+	    g_message ("GtkSocket: Message of type %d received", message));
+  
+  switch (message)
+    {
+    case XEMBED_EMBEDDED_NOTIFY:
+    case XEMBED_WINDOW_ACTIVATE:
+    case XEMBED_WINDOW_DEACTIVATE:
+    case XEMBED_MODALITY_ON:
+    case XEMBED_MODALITY_OFF:
+    case XEMBED_FOCUS_IN:
+    case XEMBED_FOCUS_OUT:
+      g_warning ("GtkSocket: Invalid _XEMBED message of type %d received", message);
+      break;
+      
+    case XEMBED_REQUEST_FOCUS:
+      fprintf (stderr, "XEMBED_REQUEST_FOCUS ");
+      _gtk_socket_claim_focus (socket, TRUE);
+      break;
+
+    case XEMBED_FOCUS_NEXT:
+      fprintf (stderr, "XEMBED_FOCUS_NEXT "); goto next;
+    case XEMBED_FOCUS_PREV:
+      fprintf (stderr, "XEMBED_FOCUS_PREV "); next:
+      _gtk_socket_advance_toplevel_focus (socket,
+					  (message == XEMBED_FOCUS_NEXT ?
+					   GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
+      break;
+      
+    case XEMBED_GTK_GRAB_KEY:
+      fprintf (stderr, "XEMBED_GTK_GRAB_KEY ");
+      _gtk_socket_add_grabbed_key (socket, data1, data2);
+      break; 
+    case XEMBED_GTK_UNGRAB_KEY:
+      fprintf (stderr, "XEMBED_GTK_UNGRAB_KEY ");
+      _gtk_socket_remove_grabbed_key (socket, data1, data2);
+      break;
+
+    case XEMBED_GRAB_KEY:
+    case XEMBED_UNGRAB_KEY:
+      break;
+      
+    default:
+      GTK_NOTE (PLUGSOCKET,
+		g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %d", message));
+      break;
+    }
+}
+
+GdkFilterReturn
+_gtk_socket_filter_func (GdkXEvent *gdk_xevent,
+			 GdkEvent  *event,
+			 gpointer   data)
+{
+  GtkSocket *socket;
+  GtkWidget *widget;
+  GdkDisplay *display;
+  XEvent *xevent;
+
+  GdkFilterReturn return_val;
+  
+  socket = GTK_SOCKET (data);
+
+  return_val = GDK_FILTER_CONTINUE;
+
+  if (socket->plug_widget)
+    return return_val;
+
+  widget = GTK_WIDGET (socket);
+  xevent = (XEvent *)gdk_xevent;
+  display = gtk_widget_get_display (widget);
+
+  fprintf (stderr, "_gtk_socket_filter_func: "); fflush (stderr);
+
+  switch (xevent->type)
+    {
+    case ClientMessage:
+      fprintf (stderr, "ClientMessage: "); fflush (stderr);
+      if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"))
+	{
+	  fprintf (stderr, "_XEMBED: "); fflush (stderr);
+	  _gtk_xembed_push_message (xevent);
+	  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_xembed_pop_message ();
+	  
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      break;
+
+    case CreateNotify:
+      {
+	XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
+
+	fprintf (stderr, "CreateNotify: "); fflush (stderr);
+	if (!socket->plug_window)
+	  {
+	    fprintf (stderr, "no plug_window: "); fflush (stderr);
+	    _gtk_socket_add_window (socket, xcwe->window, FALSE);
+
+	    if (socket->plug_window)
+	      {
+		GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window created"));
+	      }
+	  }
+	
+	return_val = GDK_FILTER_REMOVE;
+	
+	break;
+      }
+
+    case ConfigureRequest:
+      {
+	XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
+	
+	fprintf (stderr, "ConfigureRequest: "); fflush (stderr);
+	if (!socket->plug_window)
+	  _gtk_socket_add_window (socket, xcre->window, FALSE);
+	
+	if (socket->plug_window)
+	  {
+	    GtkSocketPrivate *private = _gtk_socket_get_private (socket);
+	    
+	    fprintf (stderr, "have plug_window: "); fflush (stderr);
+	    if (xcre->value_mask & (CWWidth | CWHeight))
+	      {
+		GTK_NOTE (PLUGSOCKET,
+			  g_message ("GtkSocket - configure request: %d %d",
+				     socket->request_width,
+				     socket->request_height));
+
+		private->resize_count++;
+		gtk_widget_queue_resize (widget);
+	      }
+	    else if (xcre->value_mask & (CWX | CWY))
+	      {
+		_gtk_socket_send_configure_event (socket);
+	      }
+	    /* Ignore stacking requests. */
+	    
+	    return_val = GDK_FILTER_REMOVE;
+	  }
+	break;
+      }
+
+    case DestroyNotify:
+      {
+	XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
+
+	fprintf (stderr, "DestroyNotify: "); fflush (stderr);
+	/* Note that we get destroy notifies both from SubstructureNotify on
+	 * our window and StructureNotify on socket->plug_window
+	 */
+	if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
+	  {
+	    gboolean result;
+	    
+	    fprintf (stderr, "for us: "); fflush (stderr);
+	    GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - destroy notify"));
+	    
+	    gdk_window_destroy_notify (socket->plug_window);
+	    _gtk_socket_end_embedding (socket);
+
+	    g_object_ref (widget);
+	    g_signal_emit (widget, _gtk_socket_signals[PLUG_REMOVED], 0, &result);
+	    if (!result)
+	      gtk_widget_destroy (widget);
+	    g_object_unref (widget);
+	    
+	    return_val = GDK_FILTER_REMOVE;
+	  }
+	break;
+      }
+
+    case FocusIn:
+      fprintf (stderr, "FocusIn: "); fflush (stderr);
+      if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
+	{
+	  fprintf (stderr, "EMBEDDED_APP_WANTS_FOCUS "); fflush (stderr);
+	  _gtk_socket_claim_focus (socket, TRUE);
+	}
+      return_val = GDK_FILTER_REMOVE;
+      break;
+    case FocusOut:
+      fprintf (stderr, "FocusOut: "); fflush (stderr);
+      return_val = GDK_FILTER_REMOVE;
+      break;
+    case MapRequest:
+      fprintf (stderr, "MapRequest: "); fflush (stderr);
+      if (!socket->plug_window)
+	{
+	  fprintf (stderr, "no plug_window: "); fflush (stderr);
+	  _gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE);
+	}
+	
+      if (socket->plug_window)
+	{
+	  fprintf (stderr, "now have plug_window: "); fflush (stderr);
+	  GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - Map Request"));
+
+	  _gtk_socket_map_request (socket);
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      break;
+    case PropertyNotify:
+      fprintf (stderr, "PropertyNotify: "); fflush (stderr);
+      if (socket->plug_window &&
+	  xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window))
+	{
+	  GdkDragProtocol protocol;
+
+	  fprintf (stderr, "is for plug_window: "); fflush (stderr);
+	  if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_NORMAL_HINTS"))
+	    {
+	      fprintf (stderr, "WM_NORMAL_HINTS: "); fflush (stderr);
+	      socket->have_size = FALSE;
+	      gtk_widget_queue_resize (widget);
+	      return_val = GDK_FILTER_REMOVE;
+	    }
+	  else if ((xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "XdndAware")) ||
+	      (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_RECEIVER_INFO")))
+	    {
+	      fprintf (stderr, "dnd: "); fflush (stderr);
+	      gdk_error_trap_push ();
+	      if (gdk_drag_get_protocol_for_display (display,
+						     xevent->xproperty.window,
+						     &protocol))
+		gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
+					 socket->plug_window,
+					 protocol, TRUE);
+
+	      gdk_display_sync (display);
+	      gdk_error_trap_pop ();
+	      return_val = GDK_FILTER_REMOVE;
+	    }
+	  else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"))
+	    {
+	      unsigned long flags;
+	      
+	      fprintf (stderr, "_XEMBED_INFO: "); fflush (stderr);
+	      if (xembed_get_info (socket->plug_window, NULL, &flags))
+		{
+		  gboolean was_mapped = socket->is_mapped;
+		  gboolean is_mapped = (flags & XEMBED_MAPPED) != 0;
+
+		  fprintf (stderr, "was_mapped:%d is_mapped:%d ", was_mapped, is_mapped); fflush (stderr);
+		  if (was_mapped != is_mapped)
+		    {
+		      if (is_mapped)
+			_gtk_socket_map_request (socket);
+		      else
+			{
+			  gdk_error_trap_push ();
+			  gdk_window_show (socket->plug_window);
+			  gdk_flush ();
+			  gdk_error_trap_pop ();
+			  
+			  _gtk_socket_unmap_notify (socket);
+			}
+		    }
+		}
+	      return_val = GDK_FILTER_REMOVE;
+	    }
+	}
+      break;
+    case ReparentNotify:
+      fprintf (stderr, "ReparentNotify: "); fflush (stderr);
+      {
+	XReparentEvent *xre = &xevent->xreparent;
+
+	if (!socket->plug_window && xre->parent == GDK_WINDOW_XWINDOW (widget->window))
+	  {
+	    fprintf (stderr, "no plug_window, for us: "); fflush (stderr);
+	    _gtk_socket_add_window (socket, xre->window, FALSE);
+	    
+	    if (socket->plug_window)
+	      {
+		GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window reparented"));
+	      }
+	    
+	    return_val = GDK_FILTER_REMOVE;
+	  }
+	
+	break;
+      }
+    case UnmapNotify:
+      fprintf (stderr, "UnmapNotify: "); fflush (stderr);
+      if (socket->plug_window &&
+	  xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window))
+	{
+	  fprintf (stderr, "have plug_window, for us: "); fflush (stderr);
+	  GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - Unmap notify"));
+
+	  _gtk_socket_unmap_notify (socket);
+	  return_val = GDK_FILTER_REMOVE;
+	}
+      break;
+      
+    }
+  
+  fprintf (stderr, "\n"); fflush (stderr);
+
+  return return_val;
+}
Index: gtk/gtksocket.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksocket.c,v
retrieving revision 1.63
diff -p -u -2 -r1.63 gtksocket.c
--- gtk/gtksocket.c	9 Aug 2004 16:59:52 -0000	1.63
+++ gtk/gtksocket.c	17 Mar 2005 00:36:14 -0000
@@ -37,17 +37,7 @@
 #include "gtkprivate.h"
 #include "gtksocket.h"
+#include "gtksocketprivate.h"
 #include "gtkdnd.h"
 
-#include "x11/gdkx.h"
-
-#include "gtkxembed.h"
-
-typedef struct _GtkSocketPrivate GtkSocketPrivate;
-
-struct _GtkSocketPrivate
-{
-  gint resize_count;
-};
-
 /* Forward declararations */
 
@@ -69,7 +59,4 @@ static void     gtk_socket_grab_notify  
 static gboolean gtk_socket_key_event            (GtkWidget        *widget,
 						 GdkEventKey      *event);
-static void     gtk_socket_claim_focus          (GtkSocket        *socket,
-						 gboolean          send_event);
-static void     gtk_socket_send_configure_event (GtkSocket        *socket);
 static gboolean gtk_socket_focus                (GtkWidget        *widget,
 						 GtkDirectionType  direction);
@@ -82,32 +69,12 @@ static void     gtk_socket_forall       
 
 
-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 gboolean xembed_get_info     (GdkWindow     *gdk_window,
-				     unsigned long *version,
-				     unsigned long *flags);
-
-/* From Tk */
-#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
-
 /* Local data */
 
-enum {
-  PLUG_ADDED,
-  PLUG_REMOVED,
-  LAST_SIGNAL
-}; 
-
-static guint socket_signals[LAST_SIGNAL] = { 0 };
+guint _gtk_socket_signals[LAST_SIGNAL] = { 0 };
 
 static GtkWidgetClass *parent_class = NULL;
 
-static GtkSocketPrivate *
-gtk_socket_get_private (GtkSocket *socket)
+GtkSocketPrivate *
+_gtk_socket_get_private (GtkSocket *socket)
 {
   GtkSocketPrivate *private;
@@ -204,5 +171,5 @@ gtk_socket_class_init (GtkSocketClass *c
   container_class->forall = gtk_socket_forall;
 
-  socket_signals[PLUG_ADDED] =
+  _gtk_socket_signals[PLUG_ADDED] =
     g_signal_new ("plug_added",
 		  G_OBJECT_CLASS_TYPE (class),
@@ -212,5 +179,5 @@ gtk_socket_class_init (GtkSocketClass *c
 		  _gtk_marshal_VOID__VOID,
 		  G_TYPE_NONE, 0);
-  socket_signals[PLUG_REMOVED] =
+  _gtk_socket_signals[PLUG_REMOVED] =
     g_signal_new ("plug_removed",
 		  G_OBJECT_CLASS_TYPE (class),
@@ -272,5 +239,6 @@ gtk_socket_new (void)
  **/
 void           
-gtk_socket_steal (GtkSocket *socket, GdkNativeWindow wid)
+gtk_socket_steal (GtkSocket      *socket,
+		  GdkNativeWindow wid)
 {
   g_return_if_fail (GTK_IS_SOCKET (socket));
@@ -280,5 +248,5 @@ gtk_socket_steal (GtkSocket *socket, Gdk
     gtk_widget_realize (GTK_WIDGET (socket));
 
-  gtk_socket_add_window (socket, wid, TRUE);
+  _gtk_socket_add_window (socket, wid, TRUE);
 }
 
@@ -302,5 +270,6 @@ gtk_socket_steal (GtkSocket *socket, Gdk
  **/
 void           
-gtk_socket_add_id (GtkSocket *socket, GdkNativeWindow window_id)
+gtk_socket_add_id (GtkSocket      *socket,
+		   GdkNativeWindow window_id)
 {
   g_return_if_fail (GTK_IS_SOCKET (socket));
@@ -310,30 +279,5 @@ gtk_socket_add_id (GtkSocket *socket, Gd
     gtk_widget_realize (GTK_WIDGET (socket));
 
-  gtk_socket_add_window (socket, window_id, TRUE);
-}
-
-/**
- * gtk_socket_get_id:
- * @socket_: a #GtkSocket.
- * 
- * Gets the window ID of a #GtkSocket widget, which can then
- * be used to create a client embedded inside the socket, for
- * instance with gtk_plug_new(). 
- *
- * The #GtkSocket must have already be added into a toplevel window 
- * before you can make this call.
- * 
- * Return value: the window ID for the socket
- **/
-GdkNativeWindow
-gtk_socket_get_id (GtkSocket *socket)
-{
-  g_return_val_if_fail (GTK_IS_SOCKET (socket), 0);
-  g_return_val_if_fail (GTK_WIDGET_ANCHORED (socket), 0);
-
-  if (!GTK_WIDGET_REALIZED (socket))
-    gtk_widget_realize (GTK_WIDGET (socket));
-
-  return GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window);
+  _gtk_socket_add_window (socket, window_id, TRUE);
 }
 
@@ -344,5 +288,4 @@ gtk_socket_realize (GtkWidget *widget)
   GdkWindowAttr attributes;
   gint attributes_mask;
-  XWindowAttributes xattrs;
 
   g_return_if_fail (GTK_IS_SOCKET (widget));
@@ -366,18 +309,12 @@ gtk_socket_realize (GtkWidget *widget)
 				   &attributes, attributes_mask);
   gdk_window_set_user_data (widget->window, socket);
+  fprintf (stderr, "%s: set user data for %p: %p\n", __FUNCTION__, widget->window, socket);
 
   widget->style = gtk_style_attach (widget->style, widget->window);
   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
 
-  XGetWindowAttributes (GDK_WINDOW_XDISPLAY (widget->window),
-			GDK_WINDOW_XWINDOW (widget->window),
-			&xattrs);
-
-  XSelectInput (GDK_WINDOW_XDISPLAY (widget->window),
-		GDK_WINDOW_XWINDOW (widget->window), 
-		xattrs.your_event_mask | 
-		SubstructureNotifyMask | SubstructureRedirectMask);
+  _gtk_socket_realize_window (widget->window);
 
-  gdk_window_add_filter (widget->window, gtk_socket_filter_func, widget);
+  gdk_window_add_filter (widget->window, _gtk_socket_filter_func, widget);
 
   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
@@ -390,14 +327,13 @@ gtk_socket_realize (GtkWidget *widget)
 }
 
-static void
-gtk_socket_end_embedding (GtkSocket *socket)
+void
+_gtk_socket_end_embedding (GtkSocket *socket)
 {
-  GtkSocketPrivate *private = gtk_socket_get_private (socket);
+  GtkSocketPrivate *private = _gtk_socket_get_private (socket);
   GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
   gint i;
   
   if (toplevel && GTK_IS_WINDOW (toplevel))
-    gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), 
-				    GDK_WINDOW_XWINDOW (socket->plug_window));
+    _gtk_socket_end_embeddding_toplevel (toplevel, socket->plug_window);
 
   g_object_unref (socket->plug_window);
@@ -428,5 +364,5 @@ gtk_socket_unrealize (GtkWidget *widget)
   else if (socket->plug_window)
     {
-      gtk_socket_end_embedding (socket);
+      _gtk_socket_end_embedding (socket);
     }
 
@@ -448,32 +384,5 @@ gtk_socket_size_request (GtkWidget      
     {
       if (socket->is_mapped && !socket->have_size && socket->plug_window)
-	{
-	  XSizeHints hints;
-	  long supplied;
-	  
-	  gdk_error_trap_push ();
-
-	  socket->request_width = 1;
-	  socket->request_height = 1;
-	  
-	  if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window),
-				 GDK_WINDOW_XWINDOW (socket->plug_window),
-				 &hints, &supplied))
-	    {
-	      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;
-	  
-	  gdk_error_trap_pop ();
-	}
+	_gtk_socket_size_request (socket);
 
       if (socket->is_mapped && socket->have_size)
@@ -504,4 +413,5 @@ gtk_socket_size_allocate (GtkWidget     
   if (GTK_WIDGET_REALIZED (widget))
     {
+      fprintf (stderr, "%s: calling gdk_window_move_resize on widget->window\n", __FUNCTION__); fflush (stderr);
       gdk_window_move_resize (widget->window,
 			      allocation->x, allocation->y,
@@ -517,9 +427,10 @@ gtk_socket_size_allocate (GtkWidget     
 	  child_allocation.height = allocation->height;
 
+	  fprintf (stderr, "%s: calling gtk_widget_size_allocate on socket->plug_widget\n", __FUNCTION__); fflush (stderr);
 	  gtk_widget_size_allocate (socket->plug_widget, &child_allocation);
 	}
       else if (socket->plug_window)
 	{
-	  GtkSocketPrivate *private = gtk_socket_get_private (socket);
+	  GtkSocketPrivate *private = _gtk_socket_get_private (socket);
 	  
 	  gdk_error_trap_push ();
@@ -528,4 +439,5 @@ gtk_socket_size_allocate (GtkWidget     
 	      allocation->height != socket->current_height)
 	    {
+	      fprintf (stderr, "%s: calling gdk_window_move_resize on plug_window\n", __FUNCTION__); fflush (stderr);
 	      gdk_window_move_resize (socket->plug_window,
 				      0, 0,
@@ -534,7 +446,7 @@ gtk_socket_size_allocate (GtkWidget     
 		private->resize_count--;
 	      
-	      GTK_NOTE(PLUGSOCKET,
-		       g_message ("GtkSocket - allocated: %d %d",
-				  allocation->width, allocation->height));
+	      GTK_NOTE (PLUGSOCKET,
+			g_message ("GtkSocket - allocated: %d %d",
+				   allocation->width, allocation->height));
 	      socket->current_width = allocation->width;
 	      socket->current_height = allocation->height;
@@ -543,4 +455,5 @@ gtk_socket_size_allocate (GtkWidget     
 	  if (socket->need_map)
 	    {
+	      fprintf (stderr, "%s: need_map\n", __FUNCTION__); fflush (stderr);
 	      gdk_window_show (socket->plug_window);
 	      socket->need_map = FALSE;
@@ -549,9 +462,10 @@ gtk_socket_size_allocate (GtkWidget     
 	  while (private->resize_count)
  	    {
- 	      gtk_socket_send_configure_event (socket);
+	      fprintf (stderr, "%s: resize_count=%d\n", __FUNCTION__, private->resize_count); fflush (stderr);
+ 	      _gtk_socket_send_configure_event (socket);
  	      private->resize_count--;
- 	      GTK_NOTE(PLUGSOCKET,
- 		       g_message ("GtkSocket - sending synthetic configure: %d %d",
- 				  allocation->width, allocation->height));
+ 	      GTK_NOTE (PLUGSOCKET,
+			g_message ("GtkSocket - sending synthetic configure: %d %d",
+				   allocation->width, allocation->height));
  	    }
 	  
@@ -562,10 +476,4 @@ gtk_socket_size_allocate (GtkWidget     
 }
 
-typedef struct
-{
-  guint			 accel_key;
-  GdkModifierType	 accel_mods;
-} GrabbedKey;
-
 static gboolean
 activate_key (GtkAccelGroup  *accel_group,
@@ -575,5 +483,4 @@ activate_key (GtkAccelGroup  *accel_grou
 	      GrabbedKey     *grabbed_key)
 {
-  XEvent xevent;
   GdkEvent *gdk_event = gtk_get_current_event ();
   
@@ -584,24 +491,5 @@ activate_key (GtkAccelGroup  *accel_grou
   if (gdk_event && gdk_event->type == GDK_KEY_PRESS && socket->plug_window)
     {
-      xevent.xkey.type = KeyPress;
-      xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
-      xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
-      xevent.xkey.subwindow = None;
-      xevent.xkey.time = gdk_event->key.time;
-      xevent.xkey.x = 0;
-      xevent.xkey.y = 0;
-      xevent.xkey.x_root = 0;
-      xevent.xkey.y_root = 0;
-      xevent.xkey.state = gdk_event->key.state;
-      xevent.xkey.keycode = gdk_event->key.hardware_keycode;
-      xevent.xkey.same_screen = True;
-
-      gdk_error_trap_push ();
-      XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
-		  GDK_WINDOW_XWINDOW (socket->plug_window),
-		  False, KeyPressMask, &xevent);
-      gdk_display_sync (gdk_screen_get_display (screen));
-      gdk_error_trap_pop ();
-
+      _gtk_socket_send_key_event (socket, screen, gdk_event, TRUE);
       retval = TRUE;
     }
@@ -624,8 +512,8 @@ find_accel_key (GtkAccelKey *key,
 }
 
-static void
-add_grabbed_key (GtkSocket       *socket,
-		 guint            keyval,
-		 GdkModifierType  modifiers)
+void
+_gtk_socket_add_grabbed_key (GtkSocket       *socket,
+			     guint            keyval,
+			     GdkModifierType  modifiers)
 {
   GClosure *closure;
@@ -653,8 +541,8 @@ add_grabbed_key (GtkSocket       *socket
 }
 
-static void
-remove_grabbed_key (GtkSocket      *socket,
-		    guint           keyval,
-		    GdkModifierType modifiers)
+void
+_gtk_socket_remove_grabbed_key (GtkSocket      *socket,
+				guint           keyval,
+				GdkModifierType modifiers)
 {
   gint i;
@@ -694,10 +582,5 @@ socket_update_focus_in (GtkSocket *socke
       socket->focus_in = focus_in;
 
-      if (focus_in)
-	_gtk_xembed_send_focus_message (socket->plug_window,
-					XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
-      else
-	_gtk_xembed_send_message (socket->plug_window,
-				  XEMBED_FOCUS_OUT, 0, 0, 0);
+      _gtk_socket_focus_change (socket->plug_window, focus_in);
     }
 }
@@ -720,7 +603,5 @@ socket_update_active (GtkSocket *socket)
       socket->active = active;
 
-      _gtk_xembed_send_message (socket->plug_window,
-				active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
-				0, 0, 0);
+      _gtk_socket_active_change (socket->plug_window, active);
     }
 }
@@ -772,7 +653,5 @@ gtk_socket_grab_notify (GtkWidget *widge
 
   if (!socket->same_app)
-    _gtk_xembed_send_message (GTK_SOCKET (widget)->plug_window,
-			      was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON,
-			      0, 0, 0);
+    _gtk_socket_modality_change (GTK_SOCKET (widget)->plug_window, !was_grabbed);
 }
 
@@ -786,26 +665,7 @@ gtk_socket_key_event (GtkWidget   *widge
     {
       GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window);
-      XEvent xevent;
-      
-      xevent.xkey.type = (event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
-      xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
-      xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
-      xevent.xkey.time = event->time;
-      /* FIXME, the following might cause problems for non-GTK apps */
-      xevent.xkey.x = 0;
-      xevent.xkey.y = 0;
-      xevent.xkey.x_root = 0;
-      xevent.xkey.y_root = 0;
-      xevent.xkey.state = event->state;
-      xevent.xkey.keycode = event->hardware_keycode;
-      xevent.xkey.same_screen = TRUE; /* FIXME ? */
-      
-      gdk_error_trap_push ();
-      XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
-		  GDK_WINDOW_XWINDOW (socket->plug_window),
-		  False, NoEventMask, &xevent);
-      gdk_display_sync (gtk_widget_get_display (widget));
-      gdk_error_trap_pop ();
-      
+
+      _gtk_socket_send_key_event (socket, screen, (GdkEvent *) event, FALSE);
+
       return TRUE;
     }
@@ -824,7 +684,7 @@ gtk_socket_notify (GObject    *object,
 }
 
-static void
-gtk_socket_claim_focus (GtkSocket *socket,
-			gboolean   send_event)
+void
+_gtk_socket_claim_focus (GtkSocket *socket,
+			 gboolean   send_event)
 {
   if (!send_event)
@@ -839,8 +699,8 @@ gtk_socket_claim_focus (GtkSocket *socke
 
 static gboolean
-gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
+gtk_socket_focus (GtkWidget       *widget,
+		  GtkDirectionType direction)
 {
   GtkSocket *socket;
-  gint detail = -1;
 
   g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
@@ -853,22 +713,6 @@ gtk_socket_focus (GtkWidget *widget, Gtk
   if (!gtk_widget_is_focus (widget))
     {
-      switch (direction)
-	{
-	case GTK_DIR_UP:
-	case GTK_DIR_LEFT:
-	case GTK_DIR_TAB_BACKWARD:
-	  detail = XEMBED_FOCUS_LAST;
-	  break;
-	case GTK_DIR_DOWN:
-	case GTK_DIR_RIGHT:
-	case GTK_DIR_TAB_FORWARD:
-	  detail = XEMBED_FOCUS_FIRST;
-	  break;
-	}
-      
-      _gtk_xembed_send_focus_message (socket->plug_window,
-				      XEMBED_FOCUS_IN, detail);
-
-      gtk_socket_claim_focus (socket, FALSE);
+      _gtk_socket_focus (socket->plug_window, direction);
+      _gtk_socket_claim_focus (socket, FALSE);
  
       return TRUE;
@@ -901,46 +745,8 @@ gtk_socket_forall (GtkContainer *contain
 }
 
-static void
-gtk_socket_send_configure_event (GtkSocket *socket)
-{
-  XEvent event;
-  gint x, y;
-
-  g_return_if_fail (socket->plug_window != NULL);
-
-  event.xconfigure.type = ConfigureNotify;
-
-  event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
-  event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
-
-  /* The ICCCM says that synthetic events should have root relative
-   * coordinates. We still aren't really ICCCM compliant, since
-   * we don't send events when the real toplevel is moved.
-   */
-  gdk_error_trap_push ();
-  gdk_window_get_origin (socket->plug_window, &x, &y);
-  gdk_error_trap_pop ();
-			 
-  event.xconfigure.x = x;
-  event.xconfigure.y = y;
-  event.xconfigure.width = GTK_WIDGET(socket)->allocation.width;
-  event.xconfigure.height = GTK_WIDGET(socket)->allocation.height;
-
-  event.xconfigure.border_width = 0;
-  event.xconfigure.above = None;
-  event.xconfigure.override_redirect = False;
-
-  gdk_error_trap_push ();
-  XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
-	      GDK_WINDOW_XWINDOW (socket->plug_window),
-	      False, NoEventMask, &event);
-  gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket)));
-  gdk_error_trap_pop ();
-}
-
-static void
-gtk_socket_add_window (GtkSocket        *socket,
-		       GdkNativeWindow   xid,
-		       gboolean          need_reparent)
+void
+_gtk_socket_add_window (GtkSocket       *socket,
+			GdkNativeWindow  xid,
+			gboolean         need_reparent)
 {
   GtkWidget *widget = GTK_WIDGET (socket);
@@ -954,4 +760,5 @@ gtk_socket_add_window (GtkSocket        
       g_object_ref (socket->plug_window);
       gdk_window_get_user_data (socket->plug_window, &user_data);
+      fprintf (stderr, "%s: got user data for %p: %p", __FUNCTION__, socket->plug_window, user_data);
     }
 
@@ -962,5 +769,5 @@ gtk_socket_add_window (GtkSocket        
       if (!GTK_IS_PLUG (child_widget))
 	{
-	  g_warning (G_STRLOC "Can't add non-GtkPlug to GtkSocket");
+	  g_warning (G_STRLOC ": Can't add non-GtkPlug to GtkSocket");
 	  socket->plug_window = NULL;
 	  gdk_error_trap_pop ();
@@ -975,6 +782,4 @@ gtk_socket_add_window (GtkSocket        
       GtkWidget *toplevel;
       GdkDragProtocol protocol;
-      unsigned long version;
-      unsigned long flags;
 
       gdk_error_trap_push ();
@@ -990,8 +795,7 @@ gtk_socket_add_window (GtkSocket        
 	}
 	
-      XSelectInput (GDK_DISPLAY_XDISPLAY (display),
-		    GDK_WINDOW_XWINDOW (socket->plug_window),
-		    StructureNotifyMask | PropertyChangeMask);
-      
+      _gtk_socket_select_plug_window_input (display, socket->plug_window,
+					    widget->window);
+
       if (gdk_error_trap_pop ())
 	{
@@ -1007,5 +811,8 @@ gtk_socket_add_window (GtkSocket        
       if (need_reparent)
 	{
+	  fprintf (stderr, "%s: hiding plug_window", __FUNCTION__); fflush (stderr);
+
 	  gdk_window_hide (socket->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */
+	  fprintf (stderr, "%s: reparenting", __FUNCTION__); fflush (stderr);
 	  gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
 	}
@@ -1013,17 +820,6 @@ gtk_socket_add_window (GtkSocket        
       socket->have_size = FALSE;
 
-      socket->xembed_version = -1;
-      if (xembed_get_info (socket->plug_window, &version, &flags))
-	{
-	  socket->xembed_version = MIN (GTK_XEMBED_PROTOCOL_VERSION, version);
-	  socket->is_mapped = (flags & XEMBED_MAPPED) != 0;
-	}
-      else
-	{
-	  /* FIXME, we should probably actually check the state before we started */
-	  
-	  socket->is_mapped = TRUE;
-	}
-      
+      _gtk_socket_embed_get_info (socket);
+
       socket->need_map = socket->is_mapped;
 
@@ -1035,6 +831,5 @@ gtk_socket_add_window (GtkSocket        
       gdk_error_trap_pop ();
 
-      gdk_window_add_filter (socket->plug_window, 
-			     gtk_socket_filter_func, socket);
+      gdk_window_add_filter (socket->plug_window, _gtk_socket_filter_func, socket);
 
       /* Add a pointer to the socket on our toplevel window */
@@ -1044,8 +839,6 @@ gtk_socket_add_window (GtkSocket        
 	gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
 
-      _gtk_xembed_send_message (socket->plug_window,
-				XEMBED_EMBEDDED_NOTIFY, 0,
-				GDK_WINDOW_XWINDOW (widget->window),
-				socket->xembed_version);
+      _gtk_socket_embed_notify (socket);
+
       socket_update_active (socket);
       socket_update_focus_in (socket);
@@ -1055,62 +848,32 @@ gtk_socket_add_window (GtkSocket        
 
   if (socket->plug_window)
-    g_signal_emit (socket, socket_signals[PLUG_ADDED], 0);
+    g_signal_emit (socket, _gtk_socket_signals[PLUG_ADDED], 0);
 }
 
-static gboolean
-xembed_get_info (GdkWindow     *window,
-		 unsigned long *version,
-		 unsigned long *flags)
-{
-  GdkDisplay *display = gdk_drawable_get_display (window);
-  Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
-  Atom type;
-  int format;
-  unsigned long nitems, bytes_after;
-  unsigned char *data;
-  unsigned long *data_long;
-  int status;
-  
-  gdk_error_trap_push();
-  status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
-			       GDK_WINDOW_XWINDOW (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)
+void
+_gtk_socket_map_request (GtkSocket *socket)
+{
+  if (!socket->is_mapped)
     {
-      g_warning ("_XEMBED_INFO property has wrong type\n");
-      return FALSE;
+      socket->is_mapped = TRUE;
+      socket->need_map = TRUE;
+
+      gtk_widget_queue_resize (GTK_WIDGET (socket));
     }
-  
-  if (nitems < 2)
+}
+
+void
+_gtk_socket_unmap_notify (GtkSocket *socket)
+{
+  if (socket->is_mapped)
     {
-      g_warning ("_XEMBED_INFO too short\n");
-      XFree (data);
-      return FALSE;
+      socket->is_mapped = FALSE;
+      gtk_widget_queue_resize (GTK_WIDGET (socket));
     }
-  
-  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
-advance_toplevel_focus (GtkSocket        *socket,
-			GtkDirectionType  direction)
+void
+_gtk_socket_advance_toplevel_focus (GtkSocket        *socket,
+				    GtkDirectionType  direction)
 {
   GtkBin *bin;
@@ -1148,8 +911,8 @@ advance_toplevel_focus (GtkSocket       
        * events
        */
-      if (_gtk_xembed_get_focus_wrapped ())
+      if (_gtk_socket_embed_get_focus_wrapped ())
 	return;
       else
-	_gtk_xembed_set_focus_wrapped ();
+	_gtk_socket_embed_set_focus_wrapped ();
     }
 
@@ -1175,307 +938,2 @@ advance_toplevel_focus (GtkSocket       
 }
 
-static void
-handle_xembed_message (GtkSocket        *socket,
-		       XEmbedMessageType message,
-		       glong             detail,
-		       glong             data1,
-		       glong             data2,
-		       guint32           time)
-{
-  GTK_NOTE (PLUGSOCKET,
-	    g_message ("GtkSocket: Message of type %d received", message));
-  
-  switch (message)
-    {
-    case XEMBED_EMBEDDED_NOTIFY:
-    case XEMBED_WINDOW_ACTIVATE:
-    case XEMBED_WINDOW_DEACTIVATE:
-    case XEMBED_MODALITY_ON:
-    case XEMBED_MODALITY_OFF:
-    case XEMBED_FOCUS_IN:
-    case XEMBED_FOCUS_OUT:
-      g_warning ("GtkSocket: Invalid _XEMBED message of type %d received", message);
-      break;
-      
-    case XEMBED_REQUEST_FOCUS:
-      gtk_socket_claim_focus (socket, TRUE);
-      break;
-
-    case XEMBED_FOCUS_NEXT:
-    case XEMBED_FOCUS_PREV:
-      advance_toplevel_focus (socket,
-			      (message == XEMBED_FOCUS_NEXT ?
-			       GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
-      break;
-      
-    case XEMBED_GTK_GRAB_KEY:
-      add_grabbed_key (socket, data1, data2);
-      break; 
-    case XEMBED_GTK_UNGRAB_KEY:
-      remove_grabbed_key (socket, data1, data2);
-      break;
-
-    case XEMBED_GRAB_KEY:
-    case XEMBED_UNGRAB_KEY:
-      break;
-      
-    default:
-      GTK_NOTE (PLUGSOCKET,
-		g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %d", message));
-      break;
-    }
-}
-
-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)
-{
-  GtkSocket *socket;
-  GtkWidget *widget;
-  GdkDisplay *display;
-  XEvent *xevent;
-
-  GdkFilterReturn return_val;
-  
-  socket = GTK_SOCKET (data);
-  widget = GTK_WIDGET (socket);
-  xevent = (XEvent *)gdk_xevent;
-  display = gtk_widget_get_display (widget);
-
-  return_val = GDK_FILTER_CONTINUE;
-
-  if (socket->plug_widget)
-    return return_val;
-
-  switch (xevent->type)
-    {
-    case ClientMessage:
-      if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"))
-	{
-	  _gtk_xembed_push_message (xevent);
-	  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_xembed_pop_message ();
-	  
-	  return_val = GDK_FILTER_REMOVE;
-	}
-      break;
-
-    case CreateNotify:
-      {
-	XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
-
-	if (!socket->plug_window)
-	  {
-	    gtk_socket_add_window (socket, xcwe->window, FALSE);
-
-	    if (socket->plug_window)
-	      {
-		GTK_NOTE(PLUGSOCKET,
-			 g_message ("GtkSocket - window created"));
-	      }
-	  }
-	
-	return_val = GDK_FILTER_REMOVE;
-	
-	break;
-      }
-
-    case ConfigureRequest:
-      {
-	XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
-	
-	if (!socket->plug_window)
-	  gtk_socket_add_window (socket, xcre->window, FALSE);
-	
-	if (socket->plug_window)
-	  {
-	    GtkSocketPrivate *private = gtk_socket_get_private (socket);
-	    
-	    if (xcre->value_mask & (CWWidth | CWHeight))
-	      {
-		GTK_NOTE(PLUGSOCKET,
-			 g_message ("GtkSocket - configure request: %d %d",
-				    socket->request_width,
-				    socket->request_height));
-
-		private->resize_count++;
-		gtk_widget_queue_resize (widget);
-	      }
-	    else if (xcre->value_mask & (CWX | CWY))
-	      {
-		gtk_socket_send_configure_event (socket);
-	      }
-	    /* Ignore stacking requests. */
-	    
-	    return_val = GDK_FILTER_REMOVE;
-	  }
-	break;
-      }
-
-    case DestroyNotify:
-      {
-	XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
-
-	/* Note that we get destroy notifies both from SubstructureNotify on
-	 * our window and StructureNotify on socket->plug_window
-	 */
-	if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
-	  {
-	    gboolean result;
-	    
-	    GTK_NOTE(PLUGSOCKET,
-		     g_message ("GtkSocket - destroy notify"));
-	    
-	    gdk_window_destroy_notify (socket->plug_window);
-	    gtk_socket_end_embedding (socket);
-
-	    g_object_ref (widget);
-	    g_signal_emit (widget, socket_signals[PLUG_REMOVED], 0, &result);
-	    if (!result)
-	      gtk_widget_destroy (widget);
-	    g_object_unref (widget);
-	    
-	    return_val = GDK_FILTER_REMOVE;
-	  }
-	break;
-      }
-
-    case FocusIn:
-      if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
-	{
-	  gtk_socket_claim_focus (socket, TRUE);
-	}
-      return_val = GDK_FILTER_REMOVE;
-      break;
-    case FocusOut:
-      return_val = GDK_FILTER_REMOVE;
-      break;
-    case MapRequest:
-      if (!socket->plug_window)
-	gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE);
-	
-      if (socket->plug_window)
-	{
-	  GTK_NOTE(PLUGSOCKET,
-		   g_message ("GtkSocket - Map Request"));
-
-	  map_request (socket);
-	  return_val = GDK_FILTER_REMOVE;
-	}
-      break;
-    case PropertyNotify:
-      if (socket->plug_window &&
-	  xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window))
-	{
-	  GdkDragProtocol protocol;
-
-	  if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_NORMAL_HINTS"))
-	    {
-	      socket->have_size = FALSE;
-	      gtk_widget_queue_resize (widget);
-	      return_val = GDK_FILTER_REMOVE;
-	    }
-	  else if ((xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "XdndAware")) ||
-	      (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_RECEIVER_INFO")))
-	    {
-	      gdk_error_trap_push ();
-	      if (gdk_drag_get_protocol_for_display (display,
-						     xevent->xproperty.window,
-						     &protocol))
-		gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
-					 socket->plug_window,
-					 protocol, TRUE);
-
-	      gdk_display_sync (display);
-	      gdk_error_trap_pop ();
-	      return_val = GDK_FILTER_REMOVE;
-	    }
-	  else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"))
-	    {
-	      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 ReparentNotify:
-      {
-	XReparentEvent *xre = &xevent->xreparent;
-
-	if (!socket->plug_window && xre->parent == GDK_WINDOW_XWINDOW (widget->window))
-	  {
-	    gtk_socket_add_window (socket, xre->window, FALSE);
-	    
-	    if (socket->plug_window)
-	      {
-		GTK_NOTE(PLUGSOCKET,
-			 g_message ("GtkSocket - window reparented"));
-	      }
-	    
-	    return_val = GDK_FILTER_REMOVE;
-	  }
-	
-	break;
-      }
-    case UnmapNotify:
-      if (socket->plug_window &&
-	  xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window))
-	{
-	  GTK_NOTE(PLUGSOCKET,
-		   g_message ("GtkSocket - Unmap notify"));
-
-	  unmap_notify (socket);
-	  return_val = GDK_FILTER_REMOVE;
-	}
-      break;
-      
-    }
-  
-  return return_val;
-}
Index: gtk/gtksocketprivate.h
===================================================================
RCS file: gtk/gtksocketprivate.h
diff -N gtk/gtksocketprivate.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtksocketprivate.h	17 Mar 2005 00:36:14 -0000
@@ -0,0 +1,103 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GTK_SOCKET_PRIVATE_H__
+#define __GTK_SOCKET_PRIVATE_H__
+
+enum {
+  PLUG_ADDED,
+  PLUG_REMOVED,
+  LAST_SIGNAL
+}; 
+
+typedef struct _GtkSocketPrivate GtkSocketPrivate;
+
+struct _GtkSocketPrivate
+{
+  gint resize_count;
+};
+
+typedef struct
+{
+  guint			 accel_key;
+  GdkModifierType	 accel_mods;
+} GrabbedKey;
+
+guint _gtk_socket_signals[LAST_SIGNAL];
+
+/* In gtksocket.c: */
+GtkSocketPrivate *_gtk_socket_get_private (GtkSocket *socket);
+
+void _gtk_socket_add_grabbed_key  (GtkSocket        *socket,
+				   guint             keyval,
+				   GdkModifierType   modifiers);
+void _gtk_socket_remove_grabbed_key (GtkSocket      *socket,
+				     guint           keyval,
+				     GdkModifierType modifiers);
+void _gtk_socket_claim_focus 	  (GtkSocket        *socket,
+			     	   gboolean          send_event);
+void _gtk_socket_add_window  	  (GtkSocket        *socket,
+			     	   GdkNativeWindow   xid,
+			     	   gboolean          need_reparent);
+void _gtk_socket_end_embedding    (GtkSocket        *socket);
+void _gtk_socket_map_request      (GtkSocket        *socket);
+void _gtk_socket_unmap_notify     (GtkSocket        *socket);
+void _gtk_socket_advance_toplevel_focus (GtkSocket        *socket,
+					 GtkDirectionType  direction);
+
+/* In backend-specific file (gtksocket-x11.c or gtksocket-win32.c): */
+void _gtk_socket_realize_window  (GdkWindow      *window);
+void _gtk_socket_end_embeddding_toplevel (GtkWidget *toplevel,
+					  GdkWindow *plug_window);
+void _gtk_socket_size_request    (GtkSocket 	  *socket);
+void _gtk_socket_send_key_event  (GtkSocket 	  *socket,
+				  GdkScreen 	  *screen,
+				  GdkEvent  	  *gdk_event,
+				  gboolean  	   mask_key_presses);
+void _gtk_socket_focus_change    (GdkWindow       *plug_window,
+				  gboolean         focus_in);
+void _gtk_socket_active_change   (GdkWindow       *plug_window,
+				  gboolean         active);
+void _gtk_socket_modality_change (GdkWindow       *plug_window,
+				  gboolean         modality);
+void _gtk_socket_focus           (GdkWindow       *plug_window,
+				  GtkDirectionType direction);
+
+void _gtk_socket_send_configure_event (GtkSocket *socket);
+
+void _gtk_socket_select_plug_window_input    (GdkDisplay *display,
+					      GdkWindow  *plug_window,
+					      GdkWindow  *socket_window);
+void _gtk_socket_embed_get_info  (GtkSocket *socket);
+void _gtk_socket_embed_notify    (GtkSocket *socket);
+
+gboolean _gtk_socket_embed_get_focus_wrapped (void);
+void _gtk_socket_embed_set_focus_wrapped (void);
+
+GdkFilterReturn _gtk_socket_filter_func (GdkXEvent *gdk_xevent,
+					 GdkEvent  *event,
+					 gpointer   data);
+
+#endif /* __GTK_SOCKET_PRIVATE_H__ */
Index: gtk/gtkwin32embed.c
===================================================================
RCS file: gtk/gtkwin32embed.c
diff -N gtk/gtkwin32embed.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkwin32embed.c	17 Mar 2005 00:36:18 -0000
@@ -0,0 +1,135 @@
+/* GTK - The GIMP Toolkit
+ * gtkwin32embed.c: Utilities for Win32 embedding
+ * Copyright (C) 2005, Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* By Tor Lillqvist <tml@novell.com> 2005 */
+
+#include <config.h>
+
+#include "win32/gdkwin32.h"
+
+#include "gtkwin32embed.h"
+
+static guint message_type[GTK_WIN32_EMBED_LAST];
+
+static GSList *current_messages;
+
+guint
+_gtk_win32_embed_message_type (GtkWin32EmbedMessageType type)
+{
+  if (type < 0 || type >= GTK_WIN32_EMBED_LAST)
+    return 0;
+
+  if (message_type[type] == 0)
+    {
+      char name[100];
+      sprintf (name, "gtk-win32-embed:%d", type);
+      message_type[type] = RegisterWindowMessage (name);
+    }
+
+  return message_type[type];
+}
+
+void
+_gtk_win32_embed_push_message (MSG *msg)
+{
+  MSG *message = g_new (MSG, 1);
+
+  *message = *msg;
+
+  current_messages = g_slist_prepend (current_messages, message);
+}
+
+void
+_gtk_win32_embed_pop_message (void)
+{
+  MSG *message = current_messages->data;
+
+  current_messages = g_slist_delete_link (current_messages, current_messages);
+
+  g_free (message);
+}
+
+void
+_gtk_win32_embed_send (GdkWindow               *recipient,
+		       GtkWin32EmbedMessageType message,
+		       gint		        wparam,
+		       gint			lparam)
+{
+  SendMessage (GDK_WINDOW_HWND (recipient),
+	       _gtk_win32_embed_message_type (message),
+	       wparam, lparam);
+}
+
+void
+_gtk_win32_embed_send_focus_message (GdkWindow               *recipient,
+				     GtkWin32EmbedMessageType message,
+				     gint		      wparam)
+{
+  int lparam = 0;
+
+  if (!recipient)
+    return;
+  
+  g_return_if_fail (GDK_IS_WINDOW (recipient));
+  g_return_if_fail (message == GTK_WIN32_EMBED_FOCUS_IN ||
+		    message == GTK_WIN32_EMBED_FOCUS_NEXT ||
+		    message == GTK_WIN32_EMBED_FOCUS_PREV);
+		    
+  if (current_messages)
+    {
+      MSG *msg = current_messages->data;
+      if (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_IN) ||
+	  msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_NEXT) ||
+	  msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_PREV))
+	lparam = (msg->lParam & GTK_WIN32_EMBED_FOCUS_WRAPAROUND);
+    }
+
+  _gtk_win32_embed_send (recipient, message, wparam, lparam);
+}
+
+void
+_gtk_win32_embed_set_focus_wrapped (void)
+{
+  MSG *msg;
+  
+  g_return_if_fail (current_messages != NULL);
+
+  msg = current_messages->data;
+
+  g_return_if_fail (msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_PREV) ||
+		    msg->message == _gtk_win32_embed_message_type (GTK_WIN32_EMBED_FOCUS_NEXT));
+  
+  msg->lParam |= GTK_WIN32_EMBED_FOCUS_WRAPAROUND;
+}
+
+gboolean
+_gtk_win32_embed_get_focus_wrapped (void)
+{
+  MSG *msg;
+  
+  g_return_val_if_fail (current_messages != NULL, FALSE);
+
+  msg = current_messages->data;
+
+  return (msg->lParam & GTK_WIN32_EMBED_FOCUS_WRAPAROUND) != 0;
+}
+
+
+
Index: gtk/gtkwin32embed.h
===================================================================
RCS file: gtk/gtkwin32embed.h
diff -N gtk/gtkwin32embed.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtk/gtkwin32embed.h	17 Mar 2005 00:36:18 -0000
@@ -0,0 +1,70 @@
+/* GTK - The GIMP Toolkit
+ * gtkwin32embed.h: Utilities for Win32 embedding
+ * Copyright (C) 2005, Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* By Tor Lillqvist <tml@novell.com> 2005 */
+
+#ifndef __GTK_WIN32_EMBED_H__
+#define __GTK_WIN32_EMBED_H__
+
+G_BEGIN_DECLS
+
+typedef enum {
+  GTK_WIN32_EMBED_REQUEST_EVENTS,
+  GTK_WIN32_EMBED_EVENT_PLUG_MAPPED,
+  GTK_WIN32_EMBED_WINDOW_ACTIVATE,
+  GTK_WIN32_EMBED_WINDOW_DEACTIVATE,
+  GTK_WIN32_EMBED_REQUEST_FOCUS,
+  GTK_WIN32_EMBED_FOCUS_IN,
+  GTK_WIN32_EMBED_FOCUS_OUT,
+  GTK_WIN32_EMBED_FOCUS_NEXT,
+  GTK_WIN32_EMBED_FOCUS_PREV,
+  GTK_WIN32_EMBED_GRAB_KEY,
+  GTK_WIN32_EMBED_UNGRAB_KEY,
+  GTK_WIN32_EMBED_MODALITY_ON,
+  GTK_WIN32_EMBED_MODALITY_OFF,
+  GTK_WIN32_EMBED_LAST
+} GtkWin32EmbedMessageType;
+
+/* wParam values for GTK_WIN32_EMBED_FOCUS_IN: */
+#define GTK_WIN32_EMBED_FOCUS_CURRENT 0
+#define GTK_WIN32_EMBED_FOCUS_FIRST 1
+#define GTK_WIN32_EMBED_FOCUS_LAST 2
+
+/* Flags for lParam in GTK_WIN32_EMBED_FOCUS_IN, GTK_WIN32_EMBED_FOCUS_NEXT,
+ * GTK_WIN32_EMBED_FOCUS_PREV
+ */
+#define GTK_WIN32_EMBED_FOCUS_WRAPAROUND         (1 << 0)
+
+guint _gtk_win32_embed_message_type (GtkWin32EmbedMessageType type);
+void _gtk_win32_embed_push_message (MSG *msg);
+void _gtk_win32_embed_pop_message (void);
+void _gtk_win32_embed_send (GdkWindow		    *recipient,
+			    GtkWin32EmbedMessageType message,
+			    gint		     wparam,
+			    gint                     lparam);
+void _gtk_win32_embed_send_focus_message (GdkWindow		  *recipient,
+					  GtkWin32EmbedMessageType message,
+					  gint		           wparam);
+void     _gtk_win32_embed_set_focus_wrapped  (void);
+gboolean _gtk_win32_embed_get_focus_wrapped  (void);
+
+G_END_DECLS
+
+#endif /*  __GTK_WIN32_EMBED_H__ */
