]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtksocket.c
Updated Bulgarian translation by Alexander Shopov <ash@contact.bg>
[~andy/gtk] / gtk / gtksocket.c
index 8546b959628b0b2460f4e42c67784ada23660285..9a62b9a23e517a8dae80085a507d5be9224ffa71 100644 (file)
  * 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 "gtksignal.h"
 #include "gtksocket.h"
 #include "gtkdnd.h"
 
 #include "x11/gdkx.h"
 
-#include "xembed.h"
+#include "gtkxembed.h"
+
+typedef struct _GtkSocketPrivate GtkSocketPrivate;
+
+struct _GtkSocketPrivate
+{
+  gint resize_count;
+};
 
 /* Forward declararations */
 
 static void     gtk_socket_class_init           (GtkSocketClass   *klass);
 static void     gtk_socket_init                 (GtkSocket        *socket);
 static void     gtk_socket_finalize             (GObject          *object);
+static void     gtk_socket_notify               (GObject          *object,
+                                                GParamSpec       *pspec);
 static void     gtk_socket_realize              (GtkWidget        *widget);
 static void     gtk_socket_unrealize            (GtkWidget        *widget);
 static void     gtk_socket_size_request         (GtkWidget        *widget,
@@ -54,13 +66,10 @@ static void     gtk_socket_hierarchy_changed    (GtkWidget        *widget,
                                                 GtkWidget        *old_toplevel);
 static void     gtk_socket_grab_notify          (GtkWidget        *widget,
                                                 gboolean          was_grabbed);
-static gboolean gtk_socket_key_press_event      (GtkWidget        *widget,
+static gboolean gtk_socket_key_event            (GtkWidget        *widget,
                                                 GdkEventKey      *event);
-static gboolean gtk_socket_focus_in_event       (GtkWidget        *widget,
-                                                GdkEventFocus    *event);
-static void     gtk_socket_claim_focus          (GtkSocket        *socket);
-static gboolean gtk_socket_focus_out_event      (GtkWidget        *widget,
-                                                GdkEventFocus    *event);
+static void     gtk_socket_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);
@@ -79,12 +88,6 @@ static GdkFilterReturn gtk_socket_filter_func (GdkXEvent       *gdk_xevent,
                                               GdkEvent        *event,
                                               gpointer         data);
 
-static void     send_xembed_message (GtkSocket     *socket,
-                                    glong          message,
-                                    glong          detail,
-                                    glong          data1,
-                                    glong          data2,
-                                    guint32        time);
 static gboolean xembed_get_info     (GdkWindow     *gdk_window,
                                     unsigned long *version,
                                     unsigned long *flags);
@@ -104,10 +107,33 @@ static guint socket_signals[LAST_SIGNAL] = { 0 };
 
 static GtkWidgetClass *parent_class = NULL;
 
-GtkType
+static GtkSocketPrivate *
+gtk_socket_get_private (GtkSocket *socket)
+{
+  GtkSocketPrivate *private;
+  static GQuark private_quark = 0;
+
+  if (!private_quark)
+    private_quark = g_quark_from_static_string ("gtk-socket-private");
+
+  private = g_object_get_qdata (G_OBJECT (socket), private_quark);
+
+  if (!private)
+    {
+      private = g_new0 (GtkSocketPrivate, 1);
+      private->resize_count = 0;
+      
+      g_object_set_qdata_full (G_OBJECT (socket), private_quark,
+                              private, (GDestroyNotify) g_free);
+    }
+
+  return private;
+}
+
+GType
 gtk_socket_get_type (void)
 {
-  static GtkType socket_type = 0;
+  static GType socket_type = 0;
 
   if (!socket_type)
     {
@@ -124,7 +150,8 @@ gtk_socket_get_type (void)
        (GInstanceInitFunc) gtk_socket_init,
       };
 
-      socket_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkSocket", &socket_info, 0);
+      socket_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkSocket",
+                                           &socket_info, 0);
     }
 
   return socket_type;
@@ -152,9 +179,10 @@ gtk_socket_class_init (GtkSocketClass *class)
   widget_class = (GtkWidgetClass*) class;
   container_class = (GtkContainerClass*) class;
 
-  parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
+  parent_class = g_type_class_peek_parent (class);
 
   gobject_class->finalize = gtk_socket_finalize;
+  gobject_class->notify = gtk_socket_notify;
 
   widget_class->realize = gtk_socket_realize;
   widget_class->unrealize = gtk_socket_unrealize;
@@ -162,10 +190,15 @@ gtk_socket_class_init (GtkSocketClass *class)
   widget_class->size_allocate = gtk_socket_size_allocate;
   widget_class->hierarchy_changed = gtk_socket_hierarchy_changed;
   widget_class->grab_notify = gtk_socket_grab_notify;
-  widget_class->key_press_event = gtk_socket_key_press_event;
-  widget_class->focus_in_event = gtk_socket_focus_in_event;
-  widget_class->focus_out_event = gtk_socket_focus_out_event;
+  widget_class->key_press_event = gtk_socket_key_event;
+  widget_class->key_release_event = gtk_socket_key_event;
   widget_class->focus = gtk_socket_focus;
+
+  /* We don't want to show_all/hide_all the in-process
+   * plug, if any.
+   */
+  widget_class->show_all = gtk_widget_show;
+  widget_class->hide_all = gtk_widget_hide;
   
   container_class->remove = gtk_socket_remove;
   container_class->forall = gtk_socket_forall;
@@ -177,7 +210,7 @@ gtk_socket_class_init (GtkSocketClass *class)
                  G_STRUCT_OFFSET (GtkSocketClass, plug_added),
                  NULL, NULL,
                  _gtk_marshal_VOID__VOID,
-                 GTK_TYPE_NONE, 0);
+                 G_TYPE_NONE, 0);
   socket_signals[PLUG_REMOVED] =
     g_signal_new ("plug_removed",
                  G_OBJECT_CLASS_TYPE (class),
@@ -201,6 +234,7 @@ gtk_socket_init (GtkSocket *socket)
   socket->focus_in = FALSE;
   socket->have_size = FALSE;
   socket->need_map = FALSE;
+  socket->active = FALSE;
 
   socket->accel_group = gtk_accel_group_new ();
   g_object_set_data (G_OBJECT (socket->accel_group), "gtk-socket", socket);
@@ -225,7 +259,7 @@ gtk_socket_new (void)
 
 /**
  * gtk_socket_steal:
- * @socket: a #GtkSocket
+ * @socket_: a #GtkSocket
  * @wid: the window ID of an existing toplevel window.
  * 
  * Reparents a pre-existing toplevel window into a #GtkSocket. This is
@@ -250,7 +284,7 @@ gtk_socket_steal (GtkSocket *socket, GdkNativeWindow wid)
 
 /**
  * gtk_socket_add_id:
- * @socket: a #GtkSocket
+ * @socket_: a #GtkSocket
  * @window_id: the window ID of a client participating in the XEMBED protocol.
  *
  * Adds an XEMBED client, such as a #GtkPlug, to the #GtkSocket.  The
@@ -280,7 +314,7 @@ gtk_socket_add_id (GtkSocket *socket, GdkNativeWindow window_id)
 
 /**
  * gtk_socket_get_id:
- * @socket: a #GtkSocket.
+ * @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
@@ -335,12 +369,12 @@ gtk_socket_realize (GtkWidget *widget)
   widget->style = gtk_style_attach (widget->style, widget->window);
   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
 
-  XGetWindowAttributes (GDK_DISPLAY (),
+  XGetWindowAttributes (GDK_WINDOW_XDISPLAY (widget->window),
                        GDK_WINDOW_XWINDOW (widget->window),
                        &xattrs);
 
-  XSelectInput (GDK_DISPLAY (),
-               GDK_WINDOW_XWINDOW(widget->window), 
+  XSelectInput (GDK_WINDOW_XDISPLAY (widget->window),
+               GDK_WINDOW_XWINDOW (widget->window), 
                xattrs.your_event_mask | 
                SubstructureNotifyMask | SubstructureRedirectMask);
 
@@ -352,12 +386,13 @@ gtk_socket_realize (GtkWidget *widget)
    * our window is passed to another application, SubstructureRedirectMask
    * will be set by the time the other app creates its window.
    */
-  gdk_flush();
+  gdk_display_sync (gtk_widget_get_display (widget));
 }
 
 static void
 gtk_socket_end_embedding (GtkSocket *socket)
 {
+  GtkSocketPrivate *private = gtk_socket_get_private (socket);
   GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
   gint i;
   
@@ -367,9 +402,12 @@ gtk_socket_end_embedding (GtkSocket *socket)
 
   g_object_unref (socket->plug_window);
   socket->plug_window = NULL;
+  socket->current_width = 0;
+  socket->current_height = 0;
+  private->resize_count = 0;
 
-  /* Remove from end to avoid indexes shiting. This is evil */
-  for (i = socket->accel_group->n_accels; i >= 0; i--)
+  /* Remove from end to avoid indexes shifting. This is evil */
+  for (i = socket->accel_group->n_accels - 1; i >= 0; i--)
     {
       GtkAccelGroupEntry *accel_entry = &socket->accel_group->priv_accels[i];
       gtk_accel_group_disconnect (socket->accel_group, accel_entry->closure);
@@ -414,19 +452,15 @@ gtk_socket_size_request (GtkWidget      *widget,
          long supplied;
          
          gdk_error_trap_push ();
+
+         socket->request_width = 1;
+         socket->request_height = 1;
          
-         if (XGetWMNormalHints (GDK_DISPLAY(),
+         if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window),
                                 GDK_WINDOW_XWINDOW (socket->plug_window),
                                 &hints, &supplied))
            {
-             /* This is obsolete, according the X docs, but many programs
-              * still use it */
-             if (hints.flags & (PSize | USSize))
-               {
-                 socket->request_width = hints.width;
-                 socket->request_height = hints.height;
-               }
-             else if (hints.flags & PMinSize)
+             if (hints.flags & PMinSize)
                {
                  socket->request_width = hints.min_width;
                  socket->request_height = hints.min_height;
@@ -437,7 +471,7 @@ gtk_socket_size_request (GtkWidget      *widget,
                  socket->request_height = hints.base_height;
                }
            }
-         socket->have_size = TRUE;     /* don't check again? */
+         socket->have_size = TRUE;
          
          gdk_error_trap_pop ();
        }
@@ -486,22 +520,19 @@ gtk_socket_size_allocate (GtkWidget     *widget,
        }
       else if (socket->plug_window)
        {
+         GtkSocketPrivate *private = gtk_socket_get_private (socket);
+         
          gdk_error_trap_push ();
          
-         if (!socket->need_map &&
-             (allocation->width == socket->current_width) &&
-             (allocation->height == socket->current_height))
-           {
-             gtk_socket_send_configure_event (socket);
-             GTK_NOTE(PLUGSOCKET, 
-                      g_message ("GtkSocket - allocated no change: %d %d",
-                                 allocation->width, allocation->height));
-           }
-         else
+         if (allocation->width != socket->current_width ||
+             allocation->height != socket->current_height)
            {
              gdk_window_move_resize (socket->plug_window,
                                      0, 0,
                                      allocation->width, allocation->height);
+             if (private->resize_count)
+               private->resize_count--;
+             
              GTK_NOTE(PLUGSOCKET,
                       g_message ("GtkSocket - allocated: %d %d",
                                  allocation->width, allocation->height));
@@ -515,7 +546,16 @@ gtk_socket_size_allocate (GtkWidget     *widget,
              socket->need_map = FALSE;
            }
 
-         gdk_flush ();
+         while (private->resize_count)
+           {
+             gtk_socket_send_configure_event (socket);
+             private->resize_count--;
+             GTK_NOTE(PLUGSOCKET,
+                      g_message ("GtkSocket - sending synthetic configure: %d %d",
+                                 allocation->width, allocation->height));
+           }
+         
+         gdk_display_sync (gtk_widget_get_display (widget));
          gdk_error_trap_pop ();
        }
     }
@@ -527,20 +567,25 @@ typedef struct
   GdkModifierType       accel_mods;
 } GrabbedKey;
 
-static void
-activate_key (GtkAccelGroup *accel_group,
-             GrabbedKey    *grabbed_key)
+static gboolean
+activate_key (GtkAccelGroup  *accel_group,
+             GObject        *acceleratable,
+             guint           accel_key,
+             GdkModifierType accel_mods,
+             GrabbedKey     *grabbed_key)
 {
   XEvent xevent;
   GdkEvent *gdk_event = gtk_get_current_event ();
   
   GtkSocket *socket = g_object_get_data (G_OBJECT (accel_group), "gtk-socket");
+  GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window);
+  gboolean retval = FALSE;
 
   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_ROOT_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;
@@ -552,15 +597,19 @@ activate_key (GtkAccelGroup *accel_group,
       xevent.xkey.same_screen = True;
 
       gdk_error_trap_push ();
-      XSendEvent (GDK_DISPLAY (),
+      XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
                  GDK_WINDOW_XWINDOW (socket->plug_window),
                  False, KeyPressMask, &xevent);
-      gdk_flush ();
+      gdk_display_sync (gdk_screen_get_display (screen));
       gdk_error_trap_pop ();
+
+      retval = TRUE;
     }
 
   if (gdk_event)
     gdk_event_free (gdk_event);
+
+  return retval;
 }
 
 static gboolean
@@ -620,39 +669,60 @@ remove_grabbed_key (GtkSocket      *socket,
                                      accel_entry->closure);
          return;
        }
-       
     }
 
   g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n",
             keyval, modifiers);
 }
 
-static gboolean
-toplevel_focus_in_handler (GtkWidget     *toplevel,
-                          GdkEventFocus *event,
-                          GtkSocket     *socket)
+static void
+socket_update_focus_in (GtkSocket *socket)
 {
-  /* It appears spurious focus in events can occur when
-   *  the window is hidden. So we'll just check to see if
-   *  the window is visible before actually handling the
-   *  event. (Comment from gtkwindow.c)
-   */
-  if (GTK_WIDGET_VISIBLE (toplevel))
-    send_xembed_message (socket, XEMBED_WINDOW_ACTIVATE, 0, 0, 0,
-                        gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */
+  gboolean focus_in = FALSE;
 
-  return FALSE;
+  if (socket->plug_window)
+    {
+      GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
+      if (GTK_WIDGET_TOPLEVEL (toplevel) &&
+         GTK_WINDOW (toplevel)->has_toplevel_focus &&
+         gtk_widget_is_focus (GTK_WIDGET (socket)))
+       focus_in = TRUE;
+    }
+
+  if (focus_in != socket->focus_in)
+    {
+      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);
+    }
 }
 
-static gboolean
-toplevel_focus_out_handler (GtkWidget     *toplevel,
-                           GdkEventFocus *event,
-                           GtkSocket     *socket)
+static void
+socket_update_active (GtkSocket *socket)
 {
-  send_xembed_message (socket, XEMBED_WINDOW_DEACTIVATE, 0, 0, 0,
-                      gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */
+  gboolean active = FALSE;
+
+  if (socket->plug_window)
+    {
+      GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
+      if (GTK_WIDGET_TOPLEVEL (toplevel) &&
+         GTK_WINDOW (toplevel)->is_active)
+       active = TRUE;
+    }
 
-  return FALSE;
+  if (active != socket->active)
+    {
+      socket->active = active;
+
+      _gtk_xembed_send_message (socket->plug_window,
+                               active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
+                               0, 0, 0);
+    }
 }
 
 static void
@@ -670,8 +740,12 @@ gtk_socket_hierarchy_changed (GtkWidget *widget,
       if (socket->toplevel)
        {
          gtk_window_remove_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group);
-         gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket);
-         gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket);
+         g_signal_handlers_disconnect_by_func (socket->toplevel,
+                                               socket_update_focus_in,
+                                               socket);
+         g_signal_handlers_disconnect_by_func (socket->toplevel,
+                                               socket_update_active,
+                                               socket);
        }
 
       socket->toplevel = toplevel;
@@ -679,11 +753,14 @@ gtk_socket_hierarchy_changed (GtkWidget *widget,
       if (toplevel)
        {
          gtk_window_add_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group);
-         gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_in_event",
-                             GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket);
-         gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_out_event",
-                             GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket);
+         g_signal_connect_swapped (socket->toplevel, "notify::has-toplevel-focus",
+                                   G_CALLBACK (socket_update_focus_in), socket);
+         g_signal_connect_swapped (socket->toplevel, "notify::is-active",
+                                   G_CALLBACK (socket_update_active), socket);
        }
+
+      socket_update_focus_in (socket);
+      socket_update_active (socket);
     }
 }
 
@@ -694,25 +771,25 @@ gtk_socket_grab_notify (GtkWidget *widget,
   GtkSocket *socket = GTK_SOCKET (widget);
 
   if (!socket->same_app)
-    send_xembed_message (GTK_SOCKET (widget),
-                        was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON,
-                        0, 0, 0, gtk_get_current_event_time ());
+    _gtk_xembed_send_message (GTK_SOCKET (widget)->plug_window,
+                             was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON,
+                             0, 0, 0);
 }
 
 static gboolean
-gtk_socket_key_press_event (GtkWidget   *widget,
-                           GdkEventKey *event)
+gtk_socket_key_event (GtkWidget   *widget,
+                      GdkEventKey *event)
 {
   GtkSocket *socket = GTK_SOCKET (widget);
   
   if (GTK_WIDGET_HAS_FOCUS (socket) && socket->plug_window && !socket->plug_widget)
     {
+      GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window);
       XEvent xevent;
       
-      xevent.xkey.type = KeyPress;
-      xevent.xkey.display = GDK_WINDOW_XDISPLAY (event->window);
+      xevent.xkey.type = (event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
       xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
-      xevent.xkey.root = GDK_ROOT_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;
@@ -724,10 +801,10 @@ gtk_socket_key_press_event (GtkWidget   *widget,
       xevent.xkey.same_screen = TRUE; /* FIXME ? */
       
       gdk_error_trap_push ();
-      XSendEvent (GDK_DISPLAY (),
+      XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
                  GDK_WINDOW_XWINDOW (socket->plug_window),
                  False, NoEventMask, &xevent);
-      gdk_flush ();
+      gdk_display_sync (gtk_widget_get_display (widget));
       gdk_error_trap_pop ();
       
       return TRUE;
@@ -736,72 +813,28 @@ gtk_socket_key_press_event (GtkWidget   *widget,
     return FALSE;
 }
 
-static gboolean
-gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
+static void
+gtk_socket_notify (GObject    *object,
+                  GParamSpec *pspec)
 {
-  GtkSocket *socket = GTK_SOCKET (widget);
+  if (!strcmp (pspec->name, "is_focus"))
+    return;
 
-  if (socket->plug_window)
-    send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0,
-                        gtk_get_current_event_time ());
-  
-  return TRUE;
-}
-
-static gboolean
-gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
-{
-  GtkSocket *socket = GTK_SOCKET (widget);
-
-#if 0
-  GtkWidget *toplevel;
-  toplevel = gtk_widget_get_toplevel (widget);
-  
-  if (toplevel && GTK_IS_WINDOW (toplevel))
-    {
-      XSetInputFocus (GDK_DISPLAY (),
-                     GDK_WINDOW_XWINDOW (toplevel->window),
-                     RevertToParent, CurrentTime); /* FIXME? */
-    }
-
-#endif      
-
-  if (socket->plug_window)
-    {
-      send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0,
-                          gtk_get_current_event_time ());
-    }
-
-  socket->focus_in = FALSE;
-  
-  return TRUE;
+  socket_update_focus_in (GTK_SOCKET (object));
 }
 
 static void
-gtk_socket_claim_focus (GtkSocket *socket)
+gtk_socket_claim_focus (GtkSocket *socket,
+                       gboolean   send_event)
 {
+  if (!send_event)
+    socket->focus_in = TRUE;   /* Otherwise, our notify handler will send FOCUS_IN  */
       
-  socket->focus_in = TRUE;
-  
   /* Oh, the trickery... */
   
   GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS);
   gtk_widget_grab_focus (GTK_WIDGET (socket));
   GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS);
-  
-  /* FIXME: we might grab the focus even if we don't have
-   * it as an app... (and see _focus_in ()) */
-  if (socket->plug_window)
-    {
-#if 0      
-      gdk_error_trap_push ();
-      XSetInputFocus (GDK_DISPLAY (),
-                     GDK_WINDOW_XWINDOW (socket->plug_window),
-                     RevertToParent, GDK_CURRENT_TIME);
-      gdk_flush ();
-      gdk_error_trap_pop ();
-#endif
-    }
 }
 
 static gboolean
@@ -817,7 +850,7 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
   if (socket->plug_widget)
     return gtk_widget_child_focus (socket->plug_widget, direction);
 
-  if (!GTK_WIDGET_HAS_FOCUS (widget))
+  if (!gtk_widget_is_focus (widget))
     {
       switch (direction)
        {
@@ -833,76 +866,15 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
          break;
        }
       
-      send_xembed_message (socket, XEMBED_FOCUS_IN, detail, 0, 0,
-                          gtk_get_current_event_time ());
+      _gtk_xembed_send_focus_message (socket->plug_window,
+                                     XEMBED_FOCUS_IN, detail);
 
-      GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
-      gtk_widget_grab_focus (widget);
+      gtk_socket_claim_focus (socket, FALSE);
  
       return TRUE;
     }
   else
     return FALSE;
-
-#if 0
-  if (!socket->focus_in && socket->plug_window)
-    {
-      XEvent xevent;
-
-      gtk_socket_claim_focus (socket);
-      
-      xevent.xkey.type = KeyPress;
-      xevent.xkey.display = GDK_DISPLAY ();
-      xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
-      xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
-      xevent.xkey.time = GDK_CURRENT_TIME; /* FIXME */
-      /* FIXME, the following might cause big 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 = 0;
-      xevent.xkey.same_screen = TRUE; /* FIXME ? */
-
-      switch (direction)
-       {
-       case GTK_DIR_UP:
-         xevent.xkey.keycode =  XKeysymToKeycode(GDK_DISPLAY(), GDK_Up);
-         break;
-       case GTK_DIR_DOWN:
-         xevent.xkey.keycode =  XKeysymToKeycode(GDK_DISPLAY(), GDK_Down);
-         break;
-       case GTK_DIR_LEFT:
-         xevent.xkey.keycode =  XKeysymToKeycode(GDK_DISPLAY(), GDK_Left);
-         break;
-       case GTK_DIR_RIGHT:
-         xevent.xkey.keycode =  XKeysymToKeycode(GDK_DISPLAY(), GDK_Right);
-         break;
-       case GTK_DIR_TAB_FORWARD:
-         xevent.xkey.keycode =  XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
-         break;
-       case GTK_DIR_TAB_BACKWARD:
-         xevent.xkey.keycode =  XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
-         xevent.xkey.state = ShiftMask;
-         break;
-       }
-
-
-      gdk_error_trap_push ();
-      XSendEvent (GDK_DISPLAY (),
-                 GDK_WINDOW_XWINDOW (socket->plug_window),
-                 False, NoEventMask, &xevent);
-      gdk_flush();
-      gdk_error_trap_pop ();
-      
-      return TRUE;
-    }
-  else
-    {
-      return FALSE;
-    }
-#endif  
 }
 
 static void
@@ -932,17 +904,25 @@ 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.display = GDK_DISPLAY ();
 
   event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
   event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
 
-  event.xconfigure.x = 0;
-  event.xconfigure.y = 0;
+  /* 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;
 
@@ -951,10 +931,10 @@ gtk_socket_send_configure_event (GtkSocket *socket)
   event.xconfigure.override_redirect = False;
 
   gdk_error_trap_push ();
-  XSendEvent (GDK_DISPLAY (),
+  XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
              GDK_WINDOW_XWINDOW (socket->plug_window),
              False, NoEventMask, &event);
-  gdk_flush ();
+  gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket)));
   gdk_error_trap_pop ();
 }
 
@@ -963,11 +943,11 @@ gtk_socket_add_window (GtkSocket        *socket,
                       GdkNativeWindow   xid,
                       gboolean          need_reparent)
 {
-
   GtkWidget *widget = GTK_WIDGET (socket);
+  GdkDisplay *display = gtk_widget_get_display (widget);
   gpointer user_data = NULL;
   
-  socket->plug_window = gdk_window_lookup (xid);
+  socket->plug_window = gdk_window_lookup_for_display (display, xid);
 
   if (socket->plug_window)
     {
@@ -1001,7 +981,7 @@ gtk_socket_add_window (GtkSocket        *socket,
 
       if (!socket->plug_window)
        {  
-         socket->plug_window = gdk_window_foreign_new (xid);
+         socket->plug_window = gdk_window_foreign_new_for_display (display, xid);
          if (!socket->plug_window) /* was deleted before we could get it */
            {
              gdk_error_trap_pop ();
@@ -1009,13 +989,13 @@ gtk_socket_add_window (GtkSocket        *socket,
            }
        }
        
-      XSelectInput (GDK_DISPLAY (),
-                   GDK_WINDOW_XWINDOW(socket->plug_window),
+      XSelectInput (GDK_DISPLAY_XDISPLAY (display),
+                   GDK_WINDOW_XWINDOW (socket->plug_window),
                    StructureNotifyMask | PropertyChangeMask);
       
       if (gdk_error_trap_pop ())
        {
-         gdk_window_unref (socket->plug_window);
+         g_object_unref (socket->plug_window);
          socket->plug_window = NULL;
          return;
        }
@@ -1035,23 +1015,23 @@ gtk_socket_add_window (GtkSocket        *socket,
       socket->xembed_version = -1;
       if (xembed_get_info (socket->plug_window, &version, &flags))
        {
-         socket->xembed_version = version;
+         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 = need_reparent ? TRUE : FALSE;
+         socket->is_mapped = TRUE;
        }
       
       socket->need_map = socket->is_mapped;
 
-      if (gdk_drag_get_protocol (xid, &protocol))
+      if (gdk_drag_get_protocol_for_display (display, xid, &protocol))
        gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window, 
                                 protocol, TRUE);
-      
-      gdk_flush ();
+
+      gdk_display_sync (display);
       gdk_error_trap_pop ();
 
       gdk_window_add_filter (socket->plug_window, 
@@ -1063,56 +1043,27 @@ gtk_socket_add_window (GtkSocket        *socket,
       if (toplevel && GTK_IS_WINDOW (toplevel))
        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);
+      socket_update_active (socket);
+      socket_update_focus_in (socket);
+
       gtk_widget_queue_resize (GTK_WIDGET (socket));
     }
 
   if (socket->plug_window)
-    g_signal_emit (G_OBJECT (socket), socket_signals[PLUG_ADDED], 0);
-}
-
-
-static void
-send_xembed_message (GtkSocket *socket,
-                    glong      message,
-                    glong      detail,
-                    glong      data1,
-                    glong      data2,
-                    guint32    time)
-{
-  GTK_NOTE(PLUGSOCKET,
-        g_message ("GtkSocket: Sending XEMBED message of type %ld", message));
-  
-  if (socket->plug_window)
-    {
-      XEvent xevent;
-
-      xevent.xclient.window = GDK_WINDOW_XWINDOW (socket->plug_window);
-      xevent.xclient.type = ClientMessage;
-      xevent.xclient.message_type = gdk_x11_get_xatom_by_name ("_XEMBED");
-      xevent.xclient.format = 32;
-      xevent.xclient.data.l[0] = time;
-      xevent.xclient.data.l[1] = message;
-      xevent.xclient.data.l[2] = detail;
-      xevent.xclient.data.l[3] = data1;
-      xevent.xclient.data.l[4] = data2;
-
-      gdk_error_trap_push ();
-      XSendEvent (GDK_DISPLAY (),
-                 GDK_WINDOW_XWINDOW (socket->plug_window),
-                 False, NoEventMask, &xevent);
-      gdk_flush ();
-      gdk_error_trap_pop ();
-    }
+    g_signal_emit (socket, socket_signals[PLUG_ADDED], 0);
 }
 
 static gboolean
-xembed_get_info (GdkWindow     *gdk_window,
+xembed_get_info (GdkWindow     *window,
                 unsigned long *version,
                 unsigned long *flags)
 {
-  Display *display = GDK_WINDOW_XDISPLAY (gdk_window);
-  Window window = GDK_WINDOW_XWINDOW (gdk_window);
-  Atom xembed_info_atom = gdk_x11_get_xatom_by_name ("_XEMBED_INFO");
+  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;
@@ -1121,7 +1072,8 @@ xembed_get_info (GdkWindow     *gdk_window,
   int status;
   
   gdk_error_trap_push();
-  status = XGetWindowProperty (display, window,
+  status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+                              GDK_WINDOW_XWINDOW (window),
                               xembed_info_atom,
                               0, 2, False,
                               xembed_info_atom, &type, &format,
@@ -1158,13 +1110,81 @@ xembed_get_info (GdkWindow     *gdk_window,
 }
 
 static void
-handle_xembed_message (GtkSocket *socket,
-                      glong      message,
-                      glong      detail,
-                      glong      data1,
-                      glong      data2,
-                      guint32    time)
+advance_toplevel_focus (GtkSocket        *socket,
+                       GtkDirectionType  direction)
 {
+  GtkBin *bin;
+  GtkWindow *window;
+  GtkContainer *container;
+  GtkWidget *toplevel;
+  GtkWidget *old_focus_child;
+  GtkWidget *parent;
+
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
+  if (!toplevel)
+    return;
+
+  if (!GTK_WIDGET_TOPLEVEL (toplevel) || GTK_IS_PLUG (toplevel))
+    {
+      gtk_widget_child_focus (toplevel,direction);
+      return;
+    }
+
+  container = GTK_CONTAINER (toplevel);
+  window = GTK_WINDOW (toplevel);
+  bin = GTK_BIN (toplevel);
+
+  /* This is a copy of gtk_window_focus(), modified so that we
+   * can detect wrap-around.
+   */
+  old_focus_child = container->focus_child;
+  
+  if (old_focus_child)
+    {
+      if (gtk_widget_child_focus (old_focus_child, direction))
+       return;
+
+      /* We are allowed exactly one wrap-around per sequence of focus
+       * events
+       */
+      if (_gtk_xembed_get_focus_wrapped ())
+       return;
+      else
+       _gtk_xembed_set_focus_wrapped ();
+    }
+
+  if (window->focus_widget)
+    {
+      /* Wrapped off the end, clear the focus setting for the toplevel */
+      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 (container), NULL);
+    }
+
+  /* Now try to focus the first widget in the window */
+  if (bin->child)
+    {
+      if (gtk_widget_child_focus (bin->child, direction))
+        return;
+    }
+}
+
+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:
@@ -1174,25 +1194,19 @@ handle_xembed_message (GtkSocket *socket,
     case XEMBED_MODALITY_OFF:
     case XEMBED_FOCUS_IN:
     case XEMBED_FOCUS_OUT:
-      g_warning ("GtkSocket: Invalid _XEMBED message of type %ld received", message);
+      g_warning ("GtkSocket: Invalid _XEMBED message of type %d received", message);
       break;
       
     case XEMBED_REQUEST_FOCUS:
-      gtk_socket_claim_focus (socket);
+      gtk_socket_claim_focus (socket, TRUE);
       break;
 
     case XEMBED_FOCUS_NEXT:
     case XEMBED_FOCUS_PREV:
-      {
-       GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
-       if (toplevel)
-         {
-           gtk_widget_child_focus (toplevel,
-                                    (message == XEMBED_FOCUS_NEXT ?
-                                     GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
-         }
-       break;
-      }
+      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);
@@ -1206,8 +1220,8 @@ handle_xembed_message (GtkSocket *socket,
       break;
       
     default:
-      GTK_NOTE(PLUGSOCKET,
-              g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %ld", message));
+      GTK_NOTE (PLUGSOCKET,
+               g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %d", message));
       break;
     }
 }
@@ -1239,6 +1253,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
 {
   GtkSocket *socket;
   GtkWidget *widget;
+  GdkDisplay *display;
   XEvent *xevent;
 
   GdkFilterReturn return_val;
@@ -1246,6 +1261,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
   socket = GTK_SOCKET (data);
   widget = GTK_WIDGET (socket);
   xevent = (XEvent *)gdk_xevent;
+  display = gtk_widget_get_display (widget);
 
   return_val = GDK_FILTER_CONTINUE;
 
@@ -1255,15 +1271,16 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
   switch (xevent->type)
     {
     case ClientMessage:
-      if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name ("_XEMBED"))
+      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;
        }
@@ -1279,14 +1296,8 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
 
            if (socket->plug_window)
              {
-               socket->request_width = xcwe->width;
-               socket->request_height = xcwe->height;
-               socket->have_size = TRUE;
-               
                GTK_NOTE(PLUGSOCKET,
-                        g_message ("GtkSocket - window created with size: %d %d",
-                                   socket->request_width,
-                                   socket->request_height));
+                        g_message ("GtkSocket - window created"));
              }
          }
        
@@ -1304,17 +1315,16 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
        
        if (socket->plug_window)
          {
+           GtkSocketPrivate *private = gtk_socket_get_private (socket);
+           
            if (xcre->value_mask & (CWWidth | CWHeight))
              {
-               socket->request_width = xcre->width;
-               socket->request_height = xcre->height;
-               socket->have_size = TRUE;
-               
                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))
@@ -1346,7 +1356,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
            gtk_socket_end_embedding (socket);
 
            g_object_ref (widget);
-           g_signal_emit (G_OBJECT (widget), socket_signals[PLUG_REMOVED], 0, &result);
+           g_signal_emit (widget, socket_signals[PLUG_REMOVED], 0, &result);
            if (!result)
              gtk_widget_destroy (widget);
            g_object_unref (widget);
@@ -1359,21 +1369,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
     case FocusIn:
       if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
        {
-         gtk_socket_claim_focus (socket);
-       }
-      else if (xevent->xfocus.detail == NotifyInferior)
-       {
-#if 0
-         GtkWidget *toplevel;
-         toplevel = gtk_widget_get_toplevel (widget);
-         
-         if (toplevel && GTK_IS_WINDOW (topelevel))
-           {
-             XSetInputFocus (GDK_DISPLAY (),
-                             GDK_WINDOW_XWINDOW (toplevel->window),
-                             RevertToParent, CurrentTime); /* FIXME? */
-           }
-#endif
+         gtk_socket_claim_focus (socket, TRUE);
        }
       return_val = GDK_FILTER_REMOVE;
       break;
@@ -1399,18 +1395,28 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
        {
          GdkDragProtocol protocol;
 
-         if ((xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("XdndAware")) ||
-             (xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("_MOTIF_DRAG_RECEIVER_INFO")))
+         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 (xevent->xproperty.window, &protocol))
+             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_flush ();
+
+             gdk_display_sync (display);
              gdk_error_trap_pop ();
+             return_val = GDK_FILTER_REMOVE;
            }
-         else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("_XEMBED_INFO"))
+         else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"))
            {
              unsigned long flags;
              
@@ -1434,9 +1440,8 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
                        }
                    }
                }
+             return_val = GDK_FILTER_REMOVE;
            }
-                  
-         return_val = GDK_FILTER_REMOVE;
        }
       break;
     case ReparentNotify: