]> Pileus Git - ~andy/gtk/blob - gtk/gtksocket-x11.c
Implement extended layout for plug/socket
[~andy/gtk] / gtk / gtksocket-x11.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 "config.h"
29 #include <string.h>
30
31 #include "gdk/gdkkeysyms.h"
32 #include "gtkmain.h"
33 #include "gtkmarshalers.h"
34 #include "gtkwindow.h"
35 #include "gtkplug.h"
36 #include "gtkprivate.h"
37 #include "gtksocket.h"
38 #include "gtksocketprivate.h"
39 #include "gtkdnd.h"
40
41 #include "x11/gdkx.h"
42 #include <X11/Xatom.h>
43
44 #ifdef HAVE_XFIXES
45 #include <X11/extensions/Xfixes.h>
46 #endif
47
48 #include "gtkxembed.h"
49 #include "gtkalias.h"
50
51 static gboolean xembed_get_info     (GdkWindow     *gdk_window,
52                                      unsigned long *version,
53                                      unsigned long *flags);
54
55 /* From Tk */
56 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
57
58 GdkNativeWindow
59 _gtk_socket_windowing_get_id (GtkSocket *socket)
60 {
61   return GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window);
62 }
63
64 void
65 _gtk_socket_windowing_realize_window (GtkSocket *socket)
66 {
67   GdkWindow *window = GTK_WIDGET (socket)->window;
68   XWindowAttributes xattrs;
69
70   XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
71                         GDK_WINDOW_XWINDOW (window),
72                         &xattrs);
73
74   /* Sooooo, it turns out that mozilla, as per the gtk2xt code selects
75      for input on the socket with a mask of 0x0fffff (for god knows why)
76      which includes ButtonPressMask causing a BadAccess if someone else
77      also selects for this. As per the client-side windows merge we always
78      normally selects for button press so we can emulate it on client
79      side children that selects for button press. However, we don't need
80      this for GtkSocket, so we unselect it here, fixing the crashes in
81      firefox. */
82   XSelectInput (GDK_WINDOW_XDISPLAY (window),
83                 GDK_WINDOW_XWINDOW (window), 
84                 (xattrs.your_event_mask & ~ButtonPressMask) |
85                 SubstructureNotifyMask | SubstructureRedirectMask);
86 }
87
88 void
89 _gtk_socket_windowing_end_embedding_toplevel (GtkSocket *socket)
90 {
91   gtk_window_remove_embedded_xid (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket))),
92                                   GDK_WINDOW_XWINDOW (socket->plug_window));
93 }
94
95 void
96 _gtk_socket_windowing_size_request (GtkSocket *socket)
97 {
98   XSizeHints hints;
99   long supplied;
100           
101   gdk_error_trap_push ();
102
103   socket->request_width = 1;
104   socket->request_height = 1;
105           
106   if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window),
107                          GDK_WINDOW_XWINDOW (socket->plug_window),
108                          &hints, &supplied))
109     {
110       if (hints.flags & PMinSize)
111         {
112           socket->request_width = MAX (hints.min_width, 1);
113           socket->request_height = MAX (hints.min_height, 1);
114         }
115       else if (hints.flags & PBaseSize)
116         {
117           socket->request_width = MAX (hints.base_width, 1);
118           socket->request_height = MAX (hints.base_height, 1);
119         }
120     }
121   socket->have_size = TRUE;
122   
123   gdk_error_trap_pop ();
124 }
125
126 void
127 _gtk_socket_windowing_get_natural_size (GtkSocket *socket)
128 {
129   GtkSocketPrivate *priv;
130   GdkDisplay *display;
131
132   Atom property, type;
133   int format, status;
134
135   unsigned long nitems, bytes_after;
136   unsigned char *data;
137   gint32 *data_long;
138
139   priv = _gtk_socket_get_private (socket);
140
141   priv->natural_width = 1;
142   priv->natural_height = 1;
143
144   if (GTK_WIDGET_MAPPED (socket))
145     {
146       display = gdk_drawable_get_display (socket->plug_window);
147       property = gdk_x11_get_xatom_by_name_for_display (display, "_GTK_NATURAL_SIZE");
148
149       gdk_error_trap_push ();
150       status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
151                                    GDK_WINDOW_XWINDOW (socket->plug_window),
152                                    property, 0, 2, False, XA_CARDINAL,
153                                    &type, &format, &nitems, &bytes_after,
154                                    &data);
155       gdk_error_trap_pop ();
156
157       priv->have_natural_size = TRUE;
158
159       if (Success != status || !type)
160         return;
161
162       if (type != XA_CARDINAL)
163         {
164           g_warning ("_GTK_NATURAL_SIZE property has wrong type: %d\n", (int)type);
165           return;
166         }
167
168       if (nitems < 2)
169         {
170           g_warning ("_GTK_NATURAL_SIZE too short\n");
171           XFree (data);
172           return;
173         }
174
175       data_long = (gint32*) data;
176       priv->natural_width = MAX (1, data_long[0]);
177       priv->natural_height = MAX (1, data_long[1]);
178
179       XFree (data);
180     }
181 }
182
183 void
184 _gtk_socket_windowing_send_key_event (GtkSocket *socket,
185                                       GdkEvent  *gdk_event,
186                                       gboolean   mask_key_presses)
187 {
188   XKeyEvent xkey;
189   GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window);
190
191   memset (&xkey, 0, sizeof (xkey));
192   xkey.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
193   xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
194   xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
195   xkey.subwindow = None;
196   xkey.time = gdk_event->key.time;
197   xkey.x = 0;
198   xkey.y = 0;
199   xkey.x_root = 0;
200   xkey.y_root = 0;
201   xkey.state = gdk_event->key.state;
202   xkey.keycode = gdk_event->key.hardware_keycode;
203   xkey.same_screen = True;/* FIXME ? */
204
205   gdk_error_trap_push ();
206   XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
207               GDK_WINDOW_XWINDOW (socket->plug_window),
208               False,
209               (mask_key_presses ? KeyPressMask : NoEventMask),
210               (XEvent *)&xkey);
211   gdk_display_sync (gdk_screen_get_display (screen));
212   gdk_error_trap_pop ();
213 }
214
215 void
216 _gtk_socket_windowing_focus_change (GtkSocket *socket,
217                                     gboolean   focus_in)
218 {
219   if (focus_in)
220     _gtk_xembed_send_focus_message (socket->plug_window,
221                                     XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
222   else
223     _gtk_xembed_send_message (socket->plug_window,
224                               XEMBED_FOCUS_OUT, 0, 0, 0);
225 }
226
227 void
228 _gtk_socket_windowing_update_active (GtkSocket *socket,
229                                      gboolean   active)
230 {
231   _gtk_xembed_send_message (socket->plug_window,
232                             active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
233                             0, 0, 0);
234 }
235
236 void
237 _gtk_socket_windowing_update_modality (GtkSocket *socket,
238                                        gboolean   modality)
239 {
240   _gtk_xembed_send_message (socket->plug_window,
241                             modality ? XEMBED_MODALITY_ON : XEMBED_MODALITY_OFF,
242                             0, 0, 0);
243 }
244
245 void
246 _gtk_socket_windowing_focus (GtkSocket       *socket,
247                              GtkDirectionType direction)
248 {
249   gint detail = -1;
250
251   switch (direction)
252     {
253     case GTK_DIR_UP:
254     case GTK_DIR_LEFT:
255     case GTK_DIR_TAB_BACKWARD:
256       detail = XEMBED_FOCUS_LAST;
257       break;
258     case GTK_DIR_DOWN:
259     case GTK_DIR_RIGHT:
260     case GTK_DIR_TAB_FORWARD:
261       detail = XEMBED_FOCUS_FIRST;
262       break;
263     }
264   
265   _gtk_xembed_send_focus_message (socket->plug_window, XEMBED_FOCUS_IN, detail);
266 }
267
268 void
269 _gtk_socket_windowing_send_configure_event (GtkSocket *socket)
270 {
271   XConfigureEvent xconfigure;
272   gint x, y;
273
274   g_return_if_fail (socket->plug_window != NULL);
275
276   memset (&xconfigure, 0, sizeof (xconfigure));
277   xconfigure.type = ConfigureNotify;
278
279   xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
280   xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
281
282   /* The ICCCM says that synthetic events should have root relative
283    * coordinates. We still aren't really ICCCM compliant, since
284    * we don't send events when the real toplevel is moved.
285    */
286   gdk_error_trap_push ();
287   gdk_window_get_origin (socket->plug_window, &x, &y);
288   gdk_error_trap_pop ();
289                          
290   xconfigure.x = x;
291   xconfigure.y = y;
292   xconfigure.width = GTK_WIDGET(socket)->allocation.width;
293   xconfigure.height = GTK_WIDGET(socket)->allocation.height;
294
295   xconfigure.border_width = 0;
296   xconfigure.above = None;
297   xconfigure.override_redirect = False;
298
299   gdk_error_trap_push ();
300   XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
301               GDK_WINDOW_XWINDOW (socket->plug_window),
302               False, NoEventMask, (XEvent *)&xconfigure);
303   gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket)));
304   gdk_error_trap_pop ();
305 }
306
307 void
308 _gtk_socket_windowing_select_plug_window_input (GtkSocket *socket)
309 {
310   XSelectInput (GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (socket))),
311                 GDK_WINDOW_XWINDOW (socket->plug_window),
312                 StructureNotifyMask | PropertyChangeMask);
313 }
314
315 void
316 _gtk_socket_windowing_embed_get_info (GtkSocket *socket)
317 {
318   unsigned long version;
319   unsigned long flags;
320
321   socket->xembed_version = -1;
322   if (xembed_get_info (socket->plug_window, &version, &flags))
323     {
324       socket->xembed_version = MIN (GTK_XEMBED_PROTOCOL_VERSION, version);
325       socket->is_mapped = (flags & XEMBED_MAPPED) != 0;
326     }
327   else
328     {
329       /* FIXME, we should probably actually check the state before we started */
330       socket->is_mapped = TRUE;
331     }
332 }
333
334 void
335 _gtk_socket_windowing_embed_notify (GtkSocket *socket)
336 {
337 #ifdef HAVE_XFIXES
338   GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (socket));
339
340   XFixesChangeSaveSet (GDK_DISPLAY_XDISPLAY (display),
341                        GDK_WINDOW_XWINDOW (socket->plug_window),
342                        SetModeInsert, SaveSetRoot, SaveSetUnmap);
343 #endif
344   _gtk_xembed_send_message (socket->plug_window,
345                             XEMBED_EMBEDDED_NOTIFY, 0,
346                             GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window),
347                             socket->xembed_version);
348 }
349
350 static gboolean
351 xembed_get_info (GdkWindow     *window,
352                  unsigned long *version,
353                  unsigned long *flags)
354 {
355   GdkDisplay *display = gdk_drawable_get_display (window);
356   Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
357   Atom type;
358   int format;
359   unsigned long nitems, bytes_after;
360   unsigned char *data;
361   unsigned long *data_long;
362   int status;
363   
364   gdk_error_trap_push();
365   status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
366                                GDK_WINDOW_XWINDOW (window),
367                                xembed_info_atom,
368                                0, 2, False,
369                                xembed_info_atom, &type, &format,
370                                &nitems, &bytes_after, &data);
371   gdk_error_trap_pop();
372
373   if (status != Success)
374     return FALSE;               /* Window vanished? */
375
376   if (type == None)             /* No info property */
377     return FALSE;
378
379   if (type != xembed_info_atom)
380     {
381       g_warning ("_XEMBED_INFO property has wrong type\n");
382       return FALSE;
383     }
384   
385   if (nitems < 2)
386     {
387       g_warning ("_XEMBED_INFO too short\n");
388       XFree (data);
389       return FALSE;
390     }
391   
392   data_long = (unsigned long *)data;
393   if (version)
394     *version = data_long[0];
395   if (flags)
396     *flags = data_long[1] & XEMBED_MAPPED;
397   
398   XFree (data);
399   return TRUE;
400 }
401
402 gboolean
403 _gtk_socket_windowing_embed_get_focus_wrapped (void)
404 {
405   return _gtk_xembed_get_focus_wrapped ();
406 }
407
408 void
409 _gtk_socket_windowing_embed_set_focus_wrapped (void)
410 {
411   _gtk_xembed_set_focus_wrapped ();
412 }
413
414 static void
415 handle_xembed_message (GtkSocket        *socket,
416                        XEmbedMessageType message,
417                        glong             detail,
418                        glong             data1,
419                        glong             data2,
420                        guint32           time)
421 {
422   GTK_NOTE (PLUGSOCKET,
423             g_message ("GtkSocket: %s received", _gtk_xembed_message_name (message)));
424   
425   switch (message)
426     {
427     case XEMBED_EMBEDDED_NOTIFY:
428     case XEMBED_WINDOW_ACTIVATE:
429     case XEMBED_WINDOW_DEACTIVATE:
430     case XEMBED_MODALITY_ON:
431     case XEMBED_MODALITY_OFF:
432     case XEMBED_FOCUS_IN:
433     case XEMBED_FOCUS_OUT:
434       g_warning ("GtkSocket: Invalid _XEMBED message %s received", _gtk_xembed_message_name (message));
435       break;
436       
437     case XEMBED_REQUEST_FOCUS:
438       _gtk_socket_claim_focus (socket, TRUE);
439       break;
440
441     case XEMBED_FOCUS_NEXT:
442     case XEMBED_FOCUS_PREV:
443       _gtk_socket_advance_toplevel_focus (socket,
444                                           (message == XEMBED_FOCUS_NEXT ?
445                                            GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
446       break;
447       
448     case XEMBED_GTK_GRAB_KEY:
449       _gtk_socket_add_grabbed_key (socket, data1, data2);
450       break; 
451     case XEMBED_GTK_UNGRAB_KEY:
452       _gtk_socket_remove_grabbed_key (socket, data1, data2);
453       break;
454
455     case XEMBED_GRAB_KEY:
456     case XEMBED_UNGRAB_KEY:
457       break;
458       
459     default:
460       GTK_NOTE (PLUGSOCKET,
461                 g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %d", message));
462       break;
463     }
464 }
465
466 GdkFilterReturn
467 _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
468                                    GdkEvent  *event,
469                                    gpointer   data)
470 {
471   GtkSocket *socket;
472   GtkWidget *widget;
473   GdkDisplay *display;
474   XEvent *xevent;
475
476   GdkFilterReturn return_val;
477   
478   socket = GTK_SOCKET (data);
479
480   return_val = GDK_FILTER_CONTINUE;
481
482   if (socket->plug_widget)
483     return return_val;
484
485   widget = GTK_WIDGET (socket);
486   xevent = (XEvent *)gdk_xevent;
487   display = gtk_widget_get_display (widget);
488
489   switch (xevent->type)
490     {
491     case ClientMessage:
492       if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"))
493         {
494           _gtk_xembed_push_message (xevent);
495           handle_xembed_message (socket,
496                                  xevent->xclient.data.l[1],
497                                  xevent->xclient.data.l[2],
498                                  xevent->xclient.data.l[3],
499                                  xevent->xclient.data.l[4],
500                                  xevent->xclient.data.l[0]);
501           _gtk_xembed_pop_message ();
502           
503           return_val = GDK_FILTER_REMOVE;
504         }
505       break;
506
507     case CreateNotify:
508       {
509         XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
510
511         if (!socket->plug_window)
512           {
513             _gtk_socket_add_window (socket, xcwe->window, FALSE);
514
515             if (socket->plug_window)
516               {
517                 GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window created"));
518               }
519           }
520         
521         return_val = GDK_FILTER_REMOVE;
522         
523         break;
524       }
525
526     case ConfigureRequest:
527       {
528         XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
529         
530         if (!socket->plug_window)
531           _gtk_socket_add_window (socket, xcre->window, FALSE);
532         
533         if (socket->plug_window)
534           {
535             GtkSocketPrivate *private = _gtk_socket_get_private (socket);
536             
537             if (xcre->value_mask & (CWWidth | CWHeight))
538               {
539                 GTK_NOTE (PLUGSOCKET,
540                           g_message ("GtkSocket - configure request: %d %d",
541                                      socket->request_width,
542                                      socket->request_height));
543
544                 private->resize_count++;
545                 gtk_widget_queue_resize (widget);
546               }
547             else if (xcre->value_mask & (CWX | CWY))
548               {
549                 _gtk_socket_windowing_send_configure_event (socket);
550               }
551             /* Ignore stacking requests. */
552             
553             return_val = GDK_FILTER_REMOVE;
554           }
555         break;
556       }
557
558     case DestroyNotify:
559       {
560         XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
561
562         /* Note that we get destroy notifies both from SubstructureNotify on
563          * our window and StructureNotify on socket->plug_window
564          */
565         if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
566           {
567             gboolean result;
568             
569             GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - destroy notify"));
570             
571             gdk_window_destroy_notify (socket->plug_window);
572             _gtk_socket_end_embedding (socket);
573
574             g_object_ref (widget);
575             g_signal_emit_by_name (widget, "plug-removed", &result);
576             if (!result)
577               gtk_widget_destroy (widget);
578             g_object_unref (widget);
579             
580             return_val = GDK_FILTER_REMOVE;
581           }
582         break;
583       }
584
585     case FocusIn:
586       if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
587         {
588           _gtk_socket_claim_focus (socket, TRUE);
589         }
590       return_val = GDK_FILTER_REMOVE;
591       break;
592     case FocusOut:
593       return_val = GDK_FILTER_REMOVE;
594       break;
595     case MapRequest:
596       if (!socket->plug_window)
597         {
598           _gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE);
599         }
600         
601       if (socket->plug_window)
602         {
603           GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - Map Request"));
604
605           _gtk_socket_handle_map_request (socket);
606           return_val = GDK_FILTER_REMOVE;
607         }
608       break;
609     case PropertyNotify:
610       if (socket->plug_window &&
611           xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window))
612         {
613           GdkDragProtocol protocol;
614
615           if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_NORMAL_HINTS"))
616             {
617               GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - received PropertyNotify for plug's WM_NORMAL_HINTS"));
618               socket->have_size = FALSE;
619               gtk_widget_queue_resize (widget);
620               return_val = GDK_FILTER_REMOVE;
621             }
622           else if ((xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "XdndAware")) ||
623               (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_RECEIVER_INFO")))
624             {
625               gdk_error_trap_push ();
626               if (gdk_drag_get_protocol_for_display (display,
627                                                      xevent->xproperty.window,
628                                                      &protocol))
629                 gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
630                                          socket->plug_window,
631                                          protocol, TRUE);
632
633               gdk_display_sync (display);
634               gdk_error_trap_pop ();
635               return_val = GDK_FILTER_REMOVE;
636             }
637           else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"))
638             {
639               unsigned long flags;
640               
641               if (xembed_get_info (socket->plug_window, NULL, &flags))
642                 {
643                   gboolean was_mapped = socket->is_mapped;
644                   gboolean is_mapped = (flags & XEMBED_MAPPED) != 0;
645
646                   if (was_mapped != is_mapped)
647                     {
648                       if (is_mapped)
649                         _gtk_socket_handle_map_request (socket);
650                       else
651                         {
652                           gdk_error_trap_push ();
653                           gdk_window_show (socket->plug_window);
654                           gdk_flush ();
655                           gdk_error_trap_pop ();
656                           
657                           _gtk_socket_unmap_notify (socket);
658                         }
659                     }
660                 }
661               return_val = GDK_FILTER_REMOVE;
662             }
663           else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_GTK_NATURAL_SIZE"))
664             {
665               _gtk_socket_windowing_get_natural_size (socket);
666             }
667         }
668       break;
669     case ReparentNotify:
670       {
671         XReparentEvent *xre = &xevent->xreparent;
672
673         GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - ReparentNotify received"));
674         if (!socket->plug_window && xre->parent == GDK_WINDOW_XWINDOW (widget->window))
675           {
676             _gtk_socket_add_window (socket, xre->window, FALSE);
677             
678             if (socket->plug_window)
679               {
680                 GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window reparented"));
681               }
682             
683             return_val = GDK_FILTER_REMOVE;
684           }
685         else
686           {
687             if (socket->plug_window && xre->window == GDK_WINDOW_XWINDOW (socket->plug_window) && xre->parent != GDK_WINDOW_XWINDOW (widget->window))
688               {
689                 gboolean result;
690
691                 _gtk_socket_end_embedding (socket);
692
693                 g_object_ref (widget);
694                 g_signal_emit_by_name (widget, "plug-removed", &result);
695                 if (!result)
696                   gtk_widget_destroy (widget);
697                 g_object_unref (widget);
698
699                 return_val = GDK_FILTER_REMOVE;
700               }
701           }
702
703         break;
704       }
705     case UnmapNotify:
706       if (socket->plug_window &&
707           xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window))
708         {
709           GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - Unmap notify"));
710
711           _gtk_socket_unmap_notify (socket);
712           return_val = GDK_FILTER_REMOVE;
713         }
714       break;
715       
716     }
717   
718   return return_val;
719 }