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