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