]> Pileus Git - ~andy/gtk/blob - gtk/gtksocket.c
Fix prototype for activate_key. (#108927, Jason D. Hildebrand)
[~andy/gtk] / gtk / gtksocket.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 /* By Owen Taylor <otaylor@gtk.org>              98/4/4 */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include <string.h>
29
30 #include "gdk/gdkkeysyms.h"
31 #include "gtkmain.h"
32 #include "gtkmarshalers.h"
33 #include "gtkwindow.h"
34 #include "gtkplug.h"
35 #include "gtkprivate.h"
36 #include "gtksocket.h"
37 #include "gtkdnd.h"
38
39 #include "x11/gdkx.h"
40
41 #include "xembed.h"
42
43 typedef struct _GtkSocketPrivate GtkSocketPrivate;
44
45 struct _GtkSocketPrivate
46 {
47   gint resize_count;
48 };
49
50 /* Forward declararations */
51
52 static void     gtk_socket_class_init           (GtkSocketClass   *klass);
53 static void     gtk_socket_init                 (GtkSocket        *socket);
54 static void     gtk_socket_finalize             (GObject          *object);
55 static void     gtk_socket_notify               (GObject          *object,
56                                                  GParamSpec       *pspec);
57 static void     gtk_socket_realize              (GtkWidget        *widget);
58 static void     gtk_socket_unrealize            (GtkWidget        *widget);
59 static void     gtk_socket_size_request         (GtkWidget        *widget,
60                                                  GtkRequisition   *requisition);
61 static void     gtk_socket_size_allocate        (GtkWidget        *widget,
62                                                  GtkAllocation    *allocation);
63 static void     gtk_socket_hierarchy_changed    (GtkWidget        *widget,
64                                                  GtkWidget        *old_toplevel);
65 static void     gtk_socket_grab_notify          (GtkWidget        *widget,
66                                                  gboolean          was_grabbed);
67 static gboolean gtk_socket_key_press_event      (GtkWidget        *widget,
68                                                  GdkEventKey      *event);
69 static void     gtk_socket_claim_focus          (GtkSocket        *socket,
70                                                  gboolean          send_event);
71 static void     gtk_socket_send_configure_event (GtkSocket        *socket);
72 static gboolean gtk_socket_focus                (GtkWidget        *widget,
73                                                  GtkDirectionType  direction);
74 static void     gtk_socket_remove               (GtkContainer     *container,
75                                                  GtkWidget        *widget);
76 static void     gtk_socket_forall               (GtkContainer     *container,
77                                                  gboolean          include_internals,
78                                                  GtkCallback       callback,
79                                                  gpointer          callback_data);
80
81
82 static void            gtk_socket_add_window  (GtkSocket       *socket,
83                                                GdkNativeWindow  xid,
84                                                gboolean         need_reparent);
85 static GdkFilterReturn gtk_socket_filter_func (GdkXEvent       *gdk_xevent,
86                                                GdkEvent        *event,
87                                                gpointer         data);
88
89 static void     send_xembed_message (GtkSocket     *socket,
90                                      glong          message,
91                                      glong          detail,
92                                      glong          data1,
93                                      glong          data2,
94                                      guint32        time);
95 static gboolean xembed_get_info     (GdkWindow     *gdk_window,
96                                      unsigned long *version,
97                                      unsigned long *flags);
98
99 /* From Tk */
100 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
101
102 /* Local data */
103
104 enum {
105   PLUG_ADDED,
106   PLUG_REMOVED,
107   LAST_SIGNAL
108 }; 
109
110 static guint socket_signals[LAST_SIGNAL] = { 0 };
111
112 static GtkWidgetClass *parent_class = NULL;
113
114 GtkSocketPrivate *
115 gtk_socket_get_private (GtkSocket *socket)
116 {
117   GtkSocketPrivate *private;
118   static GQuark private_quark = 0;
119
120   if (!private_quark)
121     private_quark = g_quark_from_static_string ("gtk-socket-private");
122
123   private = g_object_get_qdata (G_OBJECT (socket), private_quark);
124
125   if (!private)
126     {
127       private = g_new0 (GtkSocketPrivate, 1);
128       private->resize_count = 0;
129       
130       g_object_set_qdata_full (G_OBJECT (socket), private_quark,
131                                private, (GDestroyNotify) g_free);
132     }
133
134   return private;
135 }
136
137 GType
138 gtk_socket_get_type (void)
139 {
140   static GType socket_type = 0;
141
142   if (!socket_type)
143     {
144       static const GTypeInfo socket_info =
145       {
146         sizeof (GtkSocketClass),
147         NULL,           /* base_init */
148         NULL,           /* base_finalize */
149         (GClassInitFunc) gtk_socket_class_init,
150         NULL,           /* class_finalize */
151         NULL,           /* class_data */
152         sizeof (GtkSocket),
153         16,             /* n_preallocs */
154         (GInstanceInitFunc) gtk_socket_init,
155       };
156
157       socket_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkSocket",
158                                             &socket_info, 0);
159     }
160
161   return socket_type;
162 }
163
164 static void
165 gtk_socket_finalize (GObject *object)
166 {
167   GtkSocket *socket = GTK_SOCKET (object);
168   
169   g_object_unref (socket->accel_group);
170   socket->accel_group = NULL;
171
172   G_OBJECT_CLASS (parent_class)->finalize (object);
173 }
174
175 static void
176 gtk_socket_class_init (GtkSocketClass *class)
177 {
178   GtkWidgetClass *widget_class;
179   GtkContainerClass *container_class;
180   GObjectClass *gobject_class;
181
182   gobject_class = (GObjectClass *) class;
183   widget_class = (GtkWidgetClass*) class;
184   container_class = (GtkContainerClass*) class;
185
186   parent_class = g_type_class_peek_parent (class);
187
188   gobject_class->finalize = gtk_socket_finalize;
189   gobject_class->notify = gtk_socket_notify;
190
191   widget_class->realize = gtk_socket_realize;
192   widget_class->unrealize = gtk_socket_unrealize;
193   widget_class->size_request = gtk_socket_size_request;
194   widget_class->size_allocate = gtk_socket_size_allocate;
195   widget_class->hierarchy_changed = gtk_socket_hierarchy_changed;
196   widget_class->grab_notify = gtk_socket_grab_notify;
197   widget_class->key_press_event = gtk_socket_key_press_event;
198   widget_class->focus = gtk_socket_focus;
199   
200   container_class->remove = gtk_socket_remove;
201   container_class->forall = gtk_socket_forall;
202
203   socket_signals[PLUG_ADDED] =
204     g_signal_new ("plug_added",
205                   G_OBJECT_CLASS_TYPE (class),
206                   G_SIGNAL_RUN_LAST,
207                   G_STRUCT_OFFSET (GtkSocketClass, plug_added),
208                   NULL, NULL,
209                   _gtk_marshal_VOID__VOID,
210                   G_TYPE_NONE, 0);
211   socket_signals[PLUG_REMOVED] =
212     g_signal_new ("plug_removed",
213                   G_OBJECT_CLASS_TYPE (class),
214                   G_SIGNAL_RUN_LAST,
215                   G_STRUCT_OFFSET (GtkSocketClass, plug_removed),
216                   _gtk_boolean_handled_accumulator, NULL,
217                   _gtk_marshal_BOOLEAN__VOID,
218                   G_TYPE_BOOLEAN, 0);
219 }
220
221 static void
222 gtk_socket_init (GtkSocket *socket)
223 {
224   socket->request_width = 0;
225   socket->request_height = 0;
226   socket->current_width = 0;
227   socket->current_height = 0;
228   
229   socket->plug_window = NULL;
230   socket->plug_widget = NULL;
231   socket->focus_in = FALSE;
232   socket->have_size = FALSE;
233   socket->need_map = FALSE;
234   socket->active = FALSE;
235
236   socket->accel_group = gtk_accel_group_new ();
237   g_object_set_data (G_OBJECT (socket->accel_group), "gtk-socket", socket);
238 }
239
240 /**
241  * gtk_socket_new:
242  * 
243  * Create a new empty #GtkSocket.
244  * 
245  * Return value:  the new #GtkSocket.
246  **/
247 GtkWidget*
248 gtk_socket_new (void)
249 {
250   GtkSocket *socket;
251
252   socket = g_object_new (GTK_TYPE_SOCKET, NULL);
253
254   return GTK_WIDGET (socket);
255 }
256
257 /**
258  * gtk_socket_steal:
259  * @socket_: a #GtkSocket
260  * @wid: the window ID of an existing toplevel window.
261  * 
262  * Reparents a pre-existing toplevel window into a #GtkSocket. This is
263  * meant to embed clients that do not know about embedding into a
264  * #GtkSocket, however doing so is inherently unreliable, and using
265  * this function is not recommended.
266  *
267  * The #GtkSocket must have already be added into a toplevel window
268  *  before you can make this call.
269  **/
270 void           
271 gtk_socket_steal (GtkSocket *socket, GdkNativeWindow wid)
272 {
273   g_return_if_fail (GTK_IS_SOCKET (socket));
274   g_return_if_fail (GTK_WIDGET_ANCHORED (socket));
275
276   if (!GTK_WIDGET_REALIZED (socket))
277     gtk_widget_realize (GTK_WIDGET (socket));
278
279   gtk_socket_add_window (socket, wid, TRUE);
280 }
281
282 /**
283  * gtk_socket_add_id:
284  * @socket_: a #GtkSocket
285  * @window_id: the window ID of a client participating in the XEMBED protocol.
286  *
287  * Adds an XEMBED client, such as a #GtkPlug, to the #GtkSocket.  The
288  * client may be in the same process or in a different process. 
289  * 
290  * To embed a #GtkPlug in a #GtkSocket, you can either create the
291  * #GtkPlug with <literal>gtk_plug_new (0)</literal>, call 
292  * gtk_plug_get_id() to get the window ID of the plug, and then pass that to the
293  * gtk_socket_add_id(), or you can call gtk_socket_get_id() to get the
294  * window ID for the socket, and call gtk_plug_new() passing in that
295  * ID.
296  *
297  * The #GtkSocket must have already be added into a toplevel window
298  *  before you can make this call.
299  **/
300 void           
301 gtk_socket_add_id (GtkSocket *socket, GdkNativeWindow window_id)
302 {
303   g_return_if_fail (GTK_IS_SOCKET (socket));
304   g_return_if_fail (GTK_WIDGET_ANCHORED (socket));
305
306   if (!GTK_WIDGET_REALIZED (socket))
307     gtk_widget_realize (GTK_WIDGET (socket));
308
309   gtk_socket_add_window (socket, window_id, TRUE);
310 }
311
312 /**
313  * gtk_socket_get_id:
314  * @socket_: a #GtkSocket.
315  * 
316  * Gets the window ID of a #GtkSocket widget, which can then
317  * be used to create a client embedded inside the socket, for
318  * instance with gtk_plug_new(). 
319  *
320  * The #GtkSocket must have already be added into a toplevel window 
321  * before you can make this call.
322  * 
323  * Return value: the window ID for the socket
324  **/
325 GdkNativeWindow
326 gtk_socket_get_id (GtkSocket *socket)
327 {
328   g_return_val_if_fail (GTK_IS_SOCKET (socket), 0);
329   g_return_val_if_fail (GTK_WIDGET_ANCHORED (socket), 0);
330
331   if (!GTK_WIDGET_REALIZED (socket))
332     gtk_widget_realize (GTK_WIDGET (socket));
333
334   return GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window);
335 }
336
337 static void
338 gtk_socket_realize (GtkWidget *widget)
339 {
340   GtkSocket *socket;
341   GdkWindowAttr attributes;
342   gint attributes_mask;
343   XWindowAttributes xattrs;
344
345   g_return_if_fail (GTK_IS_SOCKET (widget));
346
347   socket = GTK_SOCKET (widget);
348   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
349
350   attributes.window_type = GDK_WINDOW_CHILD;
351   attributes.x = widget->allocation.x;
352   attributes.y = widget->allocation.y;
353   attributes.width = widget->allocation.width;
354   attributes.height = widget->allocation.height;
355   attributes.wclass = GDK_INPUT_OUTPUT;
356   attributes.visual = gtk_widget_get_visual (widget);
357   attributes.colormap = gtk_widget_get_colormap (widget);
358   attributes.event_mask = GDK_FOCUS_CHANGE_MASK;
359
360   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
361
362   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), 
363                                    &attributes, attributes_mask);
364   gdk_window_set_user_data (widget->window, socket);
365
366   widget->style = gtk_style_attach (widget->style, widget->window);
367   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
368
369   XGetWindowAttributes (GDK_WINDOW_XDISPLAY (widget->window),
370                         GDK_WINDOW_XWINDOW (widget->window),
371                         &xattrs);
372
373   XSelectInput (GDK_WINDOW_XDISPLAY (widget->window),
374                 GDK_WINDOW_XWINDOW (widget->window), 
375                 xattrs.your_event_mask | 
376                 SubstructureNotifyMask | SubstructureRedirectMask);
377
378   gdk_window_add_filter (widget->window, gtk_socket_filter_func, widget);
379
380   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
381
382   /* We sync here so that we make sure that if the XID for
383    * our window is passed to another application, SubstructureRedirectMask
384    * will be set by the time the other app creates its window.
385    */
386   gdk_display_sync (gtk_widget_get_display (widget));
387 }
388
389 static void
390 gtk_socket_end_embedding (GtkSocket *socket)
391 {
392   GtkSocketPrivate *private = gtk_socket_get_private (socket);
393   GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
394   gint i;
395   
396   if (toplevel && GTK_IS_WINDOW (toplevel))
397     gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), 
398                                     GDK_WINDOW_XWINDOW (socket->plug_window));
399
400   g_object_unref (socket->plug_window);
401   socket->plug_window = NULL;
402   private->resize_count = 0;
403
404   /* Remove from end to avoid indexes shifting. This is evil */
405   for (i = socket->accel_group->n_accels - 1; i >= 0; i--)
406     {
407       GtkAccelGroupEntry *accel_entry = &socket->accel_group->priv_accels[i];
408       gtk_accel_group_disconnect (socket->accel_group, accel_entry->closure);
409     }
410 }
411
412 static void
413 gtk_socket_unrealize (GtkWidget *widget)
414 {
415   GtkSocket *socket = GTK_SOCKET (widget);
416
417   GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED);
418
419   if (socket->plug_widget)
420     {
421       _gtk_plug_remove_from_socket (GTK_PLUG (socket->plug_widget), socket);
422     }
423   else if (socket->plug_window)
424     {
425       gtk_socket_end_embedding (socket);
426     }
427
428   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
429     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
430 }
431   
432 static void 
433 gtk_socket_size_request (GtkWidget      *widget,
434                          GtkRequisition *requisition)
435 {
436   GtkSocket *socket = GTK_SOCKET (widget);
437
438   if (socket->plug_widget)
439     {
440       gtk_widget_size_request (socket->plug_widget, requisition);
441     }
442   else
443     {
444       if (socket->is_mapped && !socket->have_size && socket->plug_window)
445         {
446           XSizeHints hints;
447           long supplied;
448           
449           gdk_error_trap_push ();
450
451           socket->request_width = 1;
452           socket->request_height = 1;
453           
454           if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window),
455                                  GDK_WINDOW_XWINDOW (socket->plug_window),
456                                  &hints, &supplied))
457             {
458               if (hints.flags & PMinSize)
459                 {
460                   socket->request_width = hints.min_width;
461                   socket->request_height = hints.min_height;
462                 }
463               else if (hints.flags & PBaseSize)
464                 {
465                   socket->request_width = hints.base_width;
466                   socket->request_height = hints.base_height;
467                 }
468             }
469           socket->have_size = TRUE;
470           
471           gdk_error_trap_pop ();
472         }
473
474       if (socket->is_mapped && socket->have_size)
475         {
476           requisition->width = MAX (socket->request_width, 1);
477           requisition->height = MAX (socket->request_height, 1);
478         }
479       else
480         {
481           requisition->width = 1;
482           requisition->height = 1;
483         }
484     }
485 }
486
487 static void
488 gtk_socket_size_allocate (GtkWidget     *widget,
489                           GtkAllocation *allocation)
490 {
491   GtkSocket *socket;
492
493   g_return_if_fail (GTK_IS_SOCKET (widget));
494   g_return_if_fail (allocation != NULL);
495
496   socket = GTK_SOCKET (widget);
497
498   widget->allocation = *allocation;
499   if (GTK_WIDGET_REALIZED (widget))
500     {
501       gdk_window_move_resize (widget->window,
502                               allocation->x, allocation->y,
503                               allocation->width, allocation->height);
504
505       if (socket->plug_widget)
506         {
507           GtkAllocation child_allocation;
508
509           child_allocation.x = 0;
510           child_allocation.y = 0;
511           child_allocation.width = allocation->width;
512           child_allocation.height = allocation->height;
513
514           gtk_widget_size_allocate (socket->plug_widget, &child_allocation);
515         }
516       else if (socket->plug_window)
517         {
518           GtkSocketPrivate *private = gtk_socket_get_private (socket);
519           
520           gdk_error_trap_push ();
521           
522           if (allocation->width != socket->current_width ||
523               allocation->height != socket->current_height)
524             {
525               gdk_window_move_resize (socket->plug_window,
526                                       0, 0,
527                                       allocation->width, allocation->height);
528               if (private->resize_count)
529                 private->resize_count--;
530               
531               GTK_NOTE(PLUGSOCKET,
532                        g_message ("GtkSocket - allocated: %d %d",
533                                   allocation->width, allocation->height));
534               socket->current_width = allocation->width;
535               socket->current_height = allocation->height;
536             }
537
538           if (socket->need_map)
539             {
540               gdk_window_show (socket->plug_window);
541               socket->need_map = FALSE;
542             }
543
544           while (private->resize_count)
545             {
546               gtk_socket_send_configure_event (socket);
547               private->resize_count--;
548               GTK_NOTE(PLUGSOCKET,
549                        g_message ("GtkSocket - sending synthetic configure: %d %d",
550                                   allocation->width, allocation->height));
551             }
552           
553           gdk_display_sync (gtk_widget_get_display (widget));
554           gdk_error_trap_pop ();
555         }
556     }
557 }
558
559 typedef struct
560 {
561   guint                  accel_key;
562   GdkModifierType        accel_mods;
563 } GrabbedKey;
564
565 static gboolean
566 activate_key (GtkAccelGroup  *accel_group,
567               GObject        *acceleratable,
568               guint           accel_key,
569               GdkModifierType accel_mods,
570               GrabbedKey     *grabbed_key)
571 {
572   XEvent xevent;
573   GdkEvent *gdk_event = gtk_get_current_event ();
574   
575   GtkSocket *socket = g_object_get_data (G_OBJECT (accel_group), "gtk-socket");
576   GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window);
577   gboolean retval = FALSE;
578
579   if (gdk_event && gdk_event->type == GDK_KEY_PRESS && socket->plug_window)
580     {
581       xevent.xkey.type = KeyPress;
582       xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
583       xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
584       xevent.xkey.subwindow = None;
585       xevent.xkey.time = gdk_event->key.time;
586       xevent.xkey.x = 0;
587       xevent.xkey.y = 0;
588       xevent.xkey.x_root = 0;
589       xevent.xkey.y_root = 0;
590       xevent.xkey.state = gdk_event->key.state;
591       xevent.xkey.keycode = gdk_event->key.hardware_keycode;
592       xevent.xkey.same_screen = True;
593
594       gdk_error_trap_push ();
595       XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
596                   GDK_WINDOW_XWINDOW (socket->plug_window),
597                   False, KeyPressMask, &xevent);
598       gdk_display_sync (gdk_screen_get_display (screen));
599       gdk_error_trap_pop ();
600
601       retval = TRUE;
602     }
603
604   if (gdk_event)
605     gdk_event_free (gdk_event);
606
607   return retval;
608 }
609
610 static gboolean
611 find_accel_key (GtkAccelKey *key,
612                 GClosure    *closure,
613                 gpointer     data)
614 {
615   GrabbedKey *grabbed_key = data;
616   
617   return (key->accel_key == grabbed_key->accel_key &&
618           key->accel_mods == grabbed_key->accel_mods);
619 }
620
621 static void
622 add_grabbed_key (GtkSocket       *socket,
623                  guint            keyval,
624                  GdkModifierType  modifiers)
625 {
626   GClosure *closure;
627   GrabbedKey *grabbed_key;
628
629   grabbed_key = g_new (GrabbedKey, 1);
630   
631   grabbed_key->accel_key = keyval;
632   grabbed_key->accel_mods = modifiers;
633
634   if (gtk_accel_group_find (socket->accel_group,
635                             find_accel_key,
636                             &grabbed_key))
637     {
638       g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n",
639                  keyval, modifiers);
640       g_free (grabbed_key);
641       return;
642     }
643
644   closure = g_cclosure_new (G_CALLBACK (activate_key), grabbed_key, (GClosureNotify)g_free);
645
646   gtk_accel_group_connect (socket->accel_group, keyval, modifiers, GTK_ACCEL_LOCKED,
647                            closure);
648 }
649
650 static void
651 remove_grabbed_key (GtkSocket      *socket,
652                     guint           keyval,
653                     GdkModifierType modifiers)
654 {
655   gint i;
656
657   for (i = 0; i < socket->accel_group->n_accels; i++)
658     {
659       GtkAccelGroupEntry *accel_entry = &socket->accel_group->priv_accels[i];
660       if (accel_entry->key.accel_key == keyval &&
661           accel_entry->key.accel_mods == modifiers)
662         {
663           gtk_accel_group_disconnect (socket->accel_group,
664                                       accel_entry->closure);
665           return;
666         }
667     }
668
669   g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n",
670              keyval, modifiers);
671 }
672
673 static void
674 socket_update_focus_in (GtkSocket *socket)
675 {
676   gboolean focus_in = FALSE;
677
678   if (socket->plug_window)
679     {
680       GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
681       if (GTK_WIDGET_TOPLEVEL (toplevel) &&
682           GTK_WINDOW (toplevel)->has_toplevel_focus &&
683           gtk_widget_is_focus (GTK_WIDGET (socket)))
684         focus_in = TRUE;
685     }
686
687   if (focus_in != socket->focus_in)
688     {
689       socket->focus_in = focus_in;
690
691       if (focus_in)
692         {
693           send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0,
694                                gtk_get_current_event_time ());
695         }
696       else
697         {
698           send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0,
699                                gtk_get_current_event_time ());
700       
701         }
702     }
703 }
704
705 static void
706 socket_update_active (GtkSocket *socket)
707 {
708   gboolean active = FALSE;
709
710   if (socket->plug_window)
711     {
712       GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
713       if (GTK_WIDGET_TOPLEVEL (toplevel) &&
714           GTK_WINDOW (toplevel)->is_active)
715         active = TRUE;
716     }
717
718   if (active != socket->active)
719     {
720       socket->active = active;
721
722       send_xembed_message (socket,
723                            active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
724                            0, 0, 0,
725                            gtk_get_current_event_time ());
726     }
727 }
728
729 static void
730 gtk_socket_hierarchy_changed (GtkWidget *widget,
731                               GtkWidget *old_toplevel)
732 {
733   GtkSocket *socket = GTK_SOCKET (widget);
734   GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
735
736   if (toplevel && !GTK_IS_WINDOW (toplevel))
737     toplevel = NULL;
738
739   if (toplevel != socket->toplevel)
740     {
741       if (socket->toplevel)
742         {
743           gtk_window_remove_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group);
744           g_signal_handlers_disconnect_by_func (socket->toplevel,
745                                                 socket_update_focus_in,
746                                                 socket);
747           g_signal_handlers_disconnect_by_func (socket->toplevel,
748                                                 socket_update_active,
749                                                 socket);
750         }
751
752       socket->toplevel = toplevel;
753
754       if (toplevel)
755         {
756           gtk_window_add_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group);
757           g_signal_connect_swapped (socket->toplevel, "notify::has-toplevel-focus",
758                                     G_CALLBACK (socket_update_focus_in), socket);
759           g_signal_connect_swapped (socket->toplevel, "notify::is-active",
760                                     G_CALLBACK (socket_update_active), socket);
761         }
762
763       socket_update_focus_in (socket);
764       socket_update_active (socket);
765     }
766 }
767
768 static void
769 gtk_socket_grab_notify (GtkWidget *widget,
770                         gboolean   was_grabbed)
771 {
772   GtkSocket *socket = GTK_SOCKET (widget);
773
774   if (!socket->same_app)
775     send_xembed_message (GTK_SOCKET (widget),
776                          was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON,
777                          0, 0, 0, gtk_get_current_event_time ());
778 }
779
780 static gboolean
781 gtk_socket_key_press_event (GtkWidget   *widget,
782                             GdkEventKey *event)
783 {
784   GtkSocket *socket = GTK_SOCKET (widget);
785   
786   if (GTK_WIDGET_HAS_FOCUS (socket) && socket->plug_window && !socket->plug_widget)
787     {
788       GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window);
789       XEvent xevent;
790       
791       xevent.xkey.type = KeyPress;
792       xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
793       xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
794       xevent.xkey.time = event->time;
795       /* FIXME, the following might cause problems for non-GTK apps */
796       xevent.xkey.x = 0;
797       xevent.xkey.y = 0;
798       xevent.xkey.x_root = 0;
799       xevent.xkey.y_root = 0;
800       xevent.xkey.state = event->state;
801       xevent.xkey.keycode = event->hardware_keycode;
802       xevent.xkey.same_screen = TRUE; /* FIXME ? */
803       
804       gdk_error_trap_push ();
805       XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
806                   GDK_WINDOW_XWINDOW (socket->plug_window),
807                   False, NoEventMask, &xevent);
808       gdk_display_sync (gtk_widget_get_display (widget));
809       gdk_error_trap_pop ();
810       
811       return TRUE;
812     }
813   else
814     return FALSE;
815 }
816
817 static void
818 gtk_socket_notify (GObject    *object,
819                    GParamSpec *pspec)
820 {
821   if (!strcmp (pspec->name, "is_focus"))
822     return;
823
824   socket_update_focus_in (GTK_SOCKET (object));
825 }
826
827 static void
828 gtk_socket_claim_focus (GtkSocket *socket,
829                         gboolean   send_event)
830 {
831   if (!send_event)
832     socket->focus_in = TRUE;    /* Otherwise, our notify handler will send FOCUS_IN  */
833       
834   /* Oh, the trickery... */
835   
836   GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS);
837   gtk_widget_grab_focus (GTK_WIDGET (socket));
838   GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS);
839 }
840
841 static gboolean
842 gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
843 {
844   GtkSocket *socket;
845   gint detail = -1;
846
847   g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
848   
849   socket = GTK_SOCKET (widget);
850
851   if (socket->plug_widget)
852     return gtk_widget_child_focus (socket->plug_widget, direction);
853
854   if (!GTK_WIDGET_HAS_FOCUS (widget))
855     {
856       switch (direction)
857         {
858         case GTK_DIR_UP:
859         case GTK_DIR_LEFT:
860         case GTK_DIR_TAB_BACKWARD:
861           detail = XEMBED_FOCUS_LAST;
862           break;
863         case GTK_DIR_DOWN:
864         case GTK_DIR_RIGHT:
865         case GTK_DIR_TAB_FORWARD:
866           detail = XEMBED_FOCUS_FIRST;
867           break;
868         }
869       
870       send_xembed_message (socket, XEMBED_FOCUS_IN, detail, 0, 0,
871                            gtk_get_current_event_time ());
872
873       gtk_socket_claim_focus (socket, FALSE);
874  
875       return TRUE;
876     }
877   else
878     return FALSE;
879 }
880
881 static void
882 gtk_socket_remove (GtkContainer *container,
883                    GtkWidget    *child)
884 {
885   GtkSocket *socket = GTK_SOCKET (container);
886
887   g_return_if_fail (child == socket->plug_widget);
888
889   _gtk_plug_remove_from_socket (GTK_PLUG (socket->plug_widget), socket);
890 }
891
892 static void
893 gtk_socket_forall (GtkContainer *container,
894                    gboolean      include_internals,
895                    GtkCallback   callback,
896                    gpointer      callback_data)
897 {
898   GtkSocket *socket = GTK_SOCKET (container);
899
900   if (socket->plug_widget)
901     (* callback) (socket->plug_widget, callback_data);
902 }
903
904 static void
905 gtk_socket_send_configure_event (GtkSocket *socket)
906 {
907   XEvent event;
908   gint x, y;
909
910   g_return_if_fail (socket->plug_window != NULL);
911
912   event.xconfigure.type = ConfigureNotify;
913
914   event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
915   event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
916
917   /* The ICCCM says that synthetic events should have root relative
918    * coordinates. We still aren't really ICCCM compliant, since
919    * we don't send events when the real toplevel is moved.
920    */
921   gdk_error_trap_push ();
922   gdk_window_get_origin (socket->plug_window, &x, &y);
923   gdk_error_trap_pop ();
924                          
925   event.xconfigure.x = x;
926   event.xconfigure.y = y;
927   event.xconfigure.width = GTK_WIDGET(socket)->allocation.width;
928   event.xconfigure.height = GTK_WIDGET(socket)->allocation.height;
929
930   event.xconfigure.border_width = 0;
931   event.xconfigure.above = None;
932   event.xconfigure.override_redirect = False;
933
934   gdk_error_trap_push ();
935   XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
936               GDK_WINDOW_XWINDOW (socket->plug_window),
937               False, NoEventMask, &event);
938   gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket)));
939   gdk_error_trap_pop ();
940 }
941
942 static void
943 gtk_socket_add_window (GtkSocket        *socket,
944                        GdkNativeWindow   xid,
945                        gboolean          need_reparent)
946 {
947   GtkWidget *widget = GTK_WIDGET (socket);
948   GdkDisplay *display = gtk_widget_get_display (widget);
949   gpointer user_data = NULL;
950   
951   socket->plug_window = gdk_window_lookup_for_display (display, xid);
952
953   if (socket->plug_window)
954     {
955       g_object_ref (socket->plug_window);
956       gdk_window_get_user_data (socket->plug_window, &user_data);
957     }
958
959   if (user_data)                /* A widget's window in this process */
960     {
961       GtkWidget *child_widget = user_data;
962
963       if (!GTK_IS_PLUG (child_widget))
964         {
965           g_warning (G_STRLOC "Can't add non-GtkPlug to GtkSocket");
966           socket->plug_window = NULL;
967           gdk_error_trap_pop ();
968           
969           return;
970         }
971
972       _gtk_plug_add_to_socket (GTK_PLUG (child_widget), socket);
973     }
974   else                          /* A foreign window */
975     {
976       GtkWidget *toplevel;
977       GdkDragProtocol protocol;
978       unsigned long version;
979       unsigned long flags;
980
981       gdk_error_trap_push ();
982
983       if (!socket->plug_window)
984         {  
985           socket->plug_window = gdk_window_foreign_new_for_display (display, xid);
986           if (!socket->plug_window) /* was deleted before we could get it */
987             {
988               gdk_error_trap_pop ();
989               return;
990             }
991         }
992         
993       XSelectInput (GDK_DISPLAY_XDISPLAY (display),
994                     GDK_WINDOW_XWINDOW (socket->plug_window),
995                     StructureNotifyMask | PropertyChangeMask);
996       
997       if (gdk_error_trap_pop ())
998         {
999           g_object_unref (socket->plug_window);
1000           socket->plug_window = NULL;
1001           return;
1002         }
1003       
1004       /* OK, we now will reliably get destroy notification on socket->plug_window */
1005
1006       gdk_error_trap_push ();
1007
1008       if (need_reparent)
1009         {
1010           gdk_window_hide (socket->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */
1011           gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
1012         }
1013
1014       socket->have_size = FALSE;
1015
1016       socket->xembed_version = -1;
1017       if (xembed_get_info (socket->plug_window, &version, &flags))
1018         {
1019           socket->xembed_version = version;
1020           socket->is_mapped = (flags & XEMBED_MAPPED) != 0;
1021         }
1022       else
1023         {
1024           /* FIXME, we should probably actually check the state before we started */
1025           
1026           socket->is_mapped = TRUE;
1027         }
1028       
1029       socket->need_map = socket->is_mapped;
1030
1031       if (gdk_drag_get_protocol_for_display (display, xid, &protocol))
1032         gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window, 
1033                                  protocol, TRUE);
1034
1035       gdk_display_sync (display);
1036       gdk_error_trap_pop ();
1037
1038       gdk_window_add_filter (socket->plug_window, 
1039                              gtk_socket_filter_func, socket);
1040
1041       /* Add a pointer to the socket on our toplevel window */
1042
1043       toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
1044       if (toplevel && GTK_IS_WINDOW (toplevel))
1045         gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
1046
1047       send_xembed_message (socket, XEMBED_EMBEDDED_NOTIFY, 0, 0, 0,
1048                            gtk_get_current_event_time ());
1049       socket_update_active (socket);
1050       socket_update_focus_in (socket);
1051
1052       gtk_widget_queue_resize (GTK_WIDGET (socket));
1053     }
1054
1055   if (socket->plug_window)
1056     g_signal_emit (socket, socket_signals[PLUG_ADDED], 0);
1057 }
1058
1059
1060 static void
1061 send_xembed_message (GtkSocket *socket,
1062                      glong      message,
1063                      glong      detail,
1064                      glong      data1,
1065                      glong      data2,
1066                      guint32    time)
1067 {
1068   GTK_NOTE(PLUGSOCKET,
1069          g_message ("GtkSocket: Sending XEMBED message of type %ld", message));
1070   
1071   if (socket->plug_window)
1072     {
1073       GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (socket));
1074       XEvent xevent;
1075
1076       xevent.xclient.window = GDK_WINDOW_XWINDOW (socket->plug_window);
1077       xevent.xclient.type = ClientMessage;
1078       xevent.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED");
1079       xevent.xclient.format = 32;
1080       xevent.xclient.data.l[0] = time;
1081       xevent.xclient.data.l[1] = message;
1082       xevent.xclient.data.l[2] = detail;
1083       xevent.xclient.data.l[3] = data1;
1084       xevent.xclient.data.l[4] = data2;
1085
1086       gdk_error_trap_push ();
1087       XSendEvent (GDK_DISPLAY_XDISPLAY (display),
1088                   GDK_WINDOW_XWINDOW (socket->plug_window),
1089                   False, NoEventMask, &xevent);
1090       gdk_display_sync (display);
1091       gdk_error_trap_pop ();
1092     }
1093 }
1094
1095 static gboolean
1096 xembed_get_info (GdkWindow     *window,
1097                  unsigned long *version,
1098                  unsigned long *flags)
1099 {
1100   GdkDisplay *display = gdk_drawable_get_display (window);
1101   Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
1102   Atom type;
1103   int format;
1104   unsigned long nitems, bytes_after;
1105   unsigned char *data;
1106   unsigned long *data_long;
1107   int status;
1108   
1109   gdk_error_trap_push();
1110   status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
1111                                GDK_WINDOW_XWINDOW (window),
1112                                xembed_info_atom,
1113                                0, 2, False,
1114                                xembed_info_atom, &type, &format,
1115                                &nitems, &bytes_after, &data);
1116   gdk_error_trap_pop();
1117
1118   if (status != Success)
1119     return FALSE;               /* Window vanished? */
1120
1121   if (type == None)             /* No info property */
1122     return FALSE;
1123
1124   if (type != xembed_info_atom)
1125     {
1126       g_warning ("_XEMBED_INFO property has wrong type\n");
1127       return FALSE;
1128     }
1129   
1130   if (nitems < 2)
1131     {
1132       g_warning ("_XEMBED_INFO too short\n");
1133       XFree (data);
1134       return FALSE;
1135     }
1136   
1137   data_long = (unsigned long *)data;
1138   if (version)
1139     *version = data_long[0];
1140   if (flags)
1141     *flags = data_long[1] & XEMBED_MAPPED;
1142   
1143   XFree (data);
1144   return TRUE;
1145 }
1146
1147 static void
1148 handle_xembed_message (GtkSocket *socket,
1149                        glong      message,
1150                        glong      detail,
1151                        glong      data1,
1152                        glong      data2,
1153                        guint32    time)
1154 {
1155   GTK_NOTE (PLUGSOCKET,
1156             g_message ("GtkSocket: Message of type %ld received", message));
1157   
1158   switch (message)
1159     {
1160     case XEMBED_EMBEDDED_NOTIFY:
1161     case XEMBED_WINDOW_ACTIVATE:
1162     case XEMBED_WINDOW_DEACTIVATE:
1163     case XEMBED_MODALITY_ON:
1164     case XEMBED_MODALITY_OFF:
1165     case XEMBED_FOCUS_IN:
1166     case XEMBED_FOCUS_OUT:
1167       g_warning ("GtkSocket: Invalid _XEMBED message of type %ld received", message);
1168       break;
1169       
1170     case XEMBED_REQUEST_FOCUS:
1171       gtk_socket_claim_focus (socket, TRUE);
1172       break;
1173
1174     case XEMBED_FOCUS_NEXT:
1175     case XEMBED_FOCUS_PREV:
1176       {
1177         GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
1178         if (toplevel)
1179           {
1180             gtk_widget_child_focus (toplevel,
1181                                     (message == XEMBED_FOCUS_NEXT ?
1182                                      GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
1183           }
1184         break;
1185       }
1186       
1187     case XEMBED_GTK_GRAB_KEY:
1188       add_grabbed_key (socket, data1, data2);
1189       break; 
1190     case XEMBED_GTK_UNGRAB_KEY:
1191       remove_grabbed_key (socket, data1, data2);
1192       break;
1193
1194     case XEMBED_GRAB_KEY:
1195     case XEMBED_UNGRAB_KEY:
1196       break;
1197       
1198     default:
1199       GTK_NOTE (PLUGSOCKET,
1200                 g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %ld", message));
1201       break;
1202     }
1203 }
1204
1205 static void
1206 map_request (GtkSocket *socket)
1207 {
1208   if (!socket->is_mapped)
1209     {
1210       socket->is_mapped = TRUE;
1211       socket->need_map = TRUE;
1212
1213       gtk_widget_queue_resize (GTK_WIDGET (socket));
1214     }
1215 }
1216
1217 static void
1218 unmap_notify (GtkSocket *socket)
1219 {
1220   if (socket->is_mapped)
1221     {
1222       socket->is_mapped = FALSE;
1223       gtk_widget_queue_resize (GTK_WIDGET (socket));
1224     }
1225 }
1226
1227 static GdkFilterReturn
1228 gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
1229 {
1230   GtkSocket *socket;
1231   GtkWidget *widget;
1232   GdkDisplay *display;
1233   XEvent *xevent;
1234
1235   GdkFilterReturn return_val;
1236   
1237   socket = GTK_SOCKET (data);
1238   widget = GTK_WIDGET (socket);
1239   xevent = (XEvent *)gdk_xevent;
1240   display = gtk_widget_get_display (widget);
1241
1242   return_val = GDK_FILTER_CONTINUE;
1243
1244   if (socket->plug_widget)
1245     return return_val;
1246
1247   switch (xevent->type)
1248     {
1249     case ClientMessage:
1250       if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"))
1251         {
1252           handle_xembed_message (socket,
1253                                  xevent->xclient.data.l[1],
1254                                  xevent->xclient.data.l[2],
1255                                  xevent->xclient.data.l[3],
1256                                  xevent->xclient.data.l[4],
1257                                  xevent->xclient.data.l[0]);
1258           
1259           
1260           return_val = GDK_FILTER_REMOVE;
1261         }
1262       break;
1263
1264     case CreateNotify:
1265       {
1266         XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
1267
1268         if (!socket->plug_window)
1269           {
1270             gtk_socket_add_window (socket, xcwe->window, FALSE);
1271
1272             if (socket->plug_window)
1273               {
1274                 GTK_NOTE(PLUGSOCKET,
1275                          g_message ("GtkSocket - window created"));
1276               }
1277           }
1278         
1279         return_val = GDK_FILTER_REMOVE;
1280         
1281         break;
1282       }
1283
1284     case ConfigureRequest:
1285       {
1286         XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
1287         
1288         if (!socket->plug_window)
1289           gtk_socket_add_window (socket, xcre->window, FALSE);
1290         
1291         if (socket->plug_window)
1292           {
1293             GtkSocketPrivate *private = gtk_socket_get_private (socket);
1294             
1295             if (xcre->value_mask & (CWWidth | CWHeight))
1296               {
1297                 GTK_NOTE(PLUGSOCKET,
1298                          g_message ("GtkSocket - configure request: %d %d",
1299                                     socket->request_width,
1300                                     socket->request_height));
1301
1302                 private->resize_count++;
1303                 gtk_widget_queue_resize (widget);
1304               }
1305             else if (xcre->value_mask & (CWX | CWY))
1306               {
1307                 gtk_socket_send_configure_event (socket);
1308               }
1309             /* Ignore stacking requests. */
1310             
1311             return_val = GDK_FILTER_REMOVE;
1312           }
1313         break;
1314       }
1315
1316     case DestroyNotify:
1317       {
1318         XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
1319
1320         /* Note that we get destroy notifies both from SubstructureNotify on
1321          * our window and StructureNotify on socket->plug_window
1322          */
1323         if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
1324           {
1325             gboolean result;
1326             
1327             GTK_NOTE(PLUGSOCKET,
1328                      g_message ("GtkSocket - destroy notify"));
1329             
1330             gdk_window_destroy_notify (socket->plug_window);
1331             gtk_socket_end_embedding (socket);
1332
1333             g_object_ref (widget);
1334             g_signal_emit (widget, socket_signals[PLUG_REMOVED], 0, &result);
1335             if (!result)
1336               gtk_widget_destroy (widget);
1337             g_object_unref (widget);
1338             
1339             return_val = GDK_FILTER_REMOVE;
1340           }
1341         break;
1342       }
1343
1344     case FocusIn:
1345       if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
1346         {
1347           gtk_socket_claim_focus (socket, TRUE);
1348         }
1349       return_val = GDK_FILTER_REMOVE;
1350       break;
1351     case FocusOut:
1352       return_val = GDK_FILTER_REMOVE;
1353       break;
1354     case MapRequest:
1355       if (!socket->plug_window)
1356         gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE);
1357         
1358       if (socket->plug_window)
1359         {
1360           GTK_NOTE(PLUGSOCKET,
1361                    g_message ("GtkSocket - Map Request"));
1362
1363           map_request (socket);
1364           return_val = GDK_FILTER_REMOVE;
1365         }
1366       break;
1367     case PropertyNotify:
1368       if (socket->plug_window &&
1369           xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window))
1370         {
1371           GdkDragProtocol protocol;
1372
1373           if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_NORMAL_HINTS"))
1374             {
1375               socket->have_size = FALSE;
1376               gtk_widget_queue_resize (widget);
1377             }
1378           else if ((xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "XdndAware")) ||
1379               (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_RECEIVER_INFO")))
1380             {
1381               gdk_error_trap_push ();
1382               if (gdk_drag_get_protocol_for_display (display,
1383                                                      xevent->xproperty.window,
1384                                                      &protocol))
1385                 gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
1386                                          socket->plug_window,
1387                                          protocol, TRUE);
1388
1389               gdk_display_sync (display);
1390               gdk_error_trap_pop ();
1391             }
1392           else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"))
1393             {
1394               unsigned long flags;
1395               
1396               if (xembed_get_info (socket->plug_window, NULL, &flags))
1397                 {
1398                   gboolean was_mapped = socket->is_mapped;
1399                   gboolean is_mapped = (flags & XEMBED_MAPPED) != 0;
1400
1401                   if (was_mapped != is_mapped)
1402                     {
1403                       if (is_mapped)
1404                         map_request (socket);
1405                       else
1406                         {
1407                           gdk_error_trap_push ();
1408                           gdk_window_show (socket->plug_window);
1409                           gdk_flush ();
1410                           gdk_error_trap_pop ();
1411                           
1412                           unmap_notify (socket);
1413                         }
1414                     }
1415                 }
1416             }
1417                    
1418           return_val = GDK_FILTER_REMOVE;
1419         }
1420       break;
1421     case ReparentNotify:
1422       {
1423         XReparentEvent *xre = &xevent->xreparent;
1424
1425         if (!socket->plug_window && xre->parent == GDK_WINDOW_XWINDOW (widget->window))
1426           {
1427             gtk_socket_add_window (socket, xre->window, FALSE);
1428             
1429             if (socket->plug_window)
1430               {
1431                 GTK_NOTE(PLUGSOCKET,
1432                          g_message ("GtkSocket - window reparented"));
1433               }
1434             
1435             return_val = GDK_FILTER_REMOVE;
1436           }
1437         
1438         break;
1439       }
1440     case UnmapNotify:
1441       if (socket->plug_window &&
1442           xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window))
1443         {
1444           GTK_NOTE(PLUGSOCKET,
1445                    g_message ("GtkSocket - Unmap notify"));
1446
1447           unmap_notify (socket);
1448           return_val = GDK_FILTER_REMOVE;
1449         }
1450       break;
1451       
1452     }
1453   
1454   return return_val;
1455 }