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