forked from AuroraMiddleware/gtk
84254039f2
Although it isnt' allowed by the XEMBED protocol, its possible that the plug window will be reparented out of the socket without the socket having done so. See bug 123569. Patch by David Jander.
658 lines
18 KiB
C
658 lines
18 KiB
C
/* GTK - The GIMP Toolkit
|
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
/* By Owen Taylor <otaylor@gtk.org> 98/4/4 */
|
|
|
|
/*
|
|
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
|
* file for a list of people on the GTK+ Team. See the ChangeLog
|
|
* files for a list of changes. These files are distributed with
|
|
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <string.h>
|
|
|
|
#include "gdk/gdkkeysyms.h"
|
|
#include "gtkmain.h"
|
|
#include "gtkmarshalers.h"
|
|
#include "gtkwindow.h"
|
|
#include "gtkplug.h"
|
|
#include "gtkprivate.h"
|
|
#include "gtksocket.h"
|
|
#include "gtksocketprivate.h"
|
|
#include "gtkdnd.h"
|
|
|
|
#include "x11/gdkx.h"
|
|
|
|
#ifdef HAVE_XFIXES
|
|
#include <X11/extensions/Xfixes.h>
|
|
#endif
|
|
|
|
#include "gtkxembed.h"
|
|
#include "gtkalias.h"
|
|
|
|
static gboolean xembed_get_info (GdkWindow *gdk_window,
|
|
unsigned long *version,
|
|
unsigned long *flags);
|
|
|
|
/* From Tk */
|
|
#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
|
|
|
|
GdkNativeWindow
|
|
_gtk_socket_windowing_get_id (GtkSocket *socket)
|
|
{
|
|
return GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window);
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_realize_window (GtkSocket *socket)
|
|
{
|
|
GdkWindow *window = GTK_WIDGET (socket)->window;
|
|
XWindowAttributes xattrs;
|
|
|
|
XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
|
|
GDK_WINDOW_XWINDOW (window),
|
|
&xattrs);
|
|
|
|
/* Sooooo, it turns out that mozilla, as per the gtk2xt code selects
|
|
for input on the socket with a mask of 0x0fffff (for god knows why)
|
|
which includes ButtonPressMask causing a BadAccess if someone else
|
|
also selects for this. As per the client-side windows merge we always
|
|
normally selects for button press so we can emulate it on client
|
|
side children that selects for button press. However, we don't need
|
|
this for GtkSocket, so we unselect it here, fixing the crashes in
|
|
firefox. */
|
|
XSelectInput (GDK_WINDOW_XDISPLAY (window),
|
|
GDK_WINDOW_XWINDOW (window),
|
|
(xattrs.your_event_mask & ~ButtonPressMask) |
|
|
SubstructureNotifyMask | SubstructureRedirectMask);
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_end_embedding_toplevel (GtkSocket *socket)
|
|
{
|
|
gtk_window_remove_embedded_xid (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket))),
|
|
GDK_WINDOW_XWINDOW (socket->plug_window));
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_size_request (GtkSocket *socket)
|
|
{
|
|
XSizeHints hints;
|
|
long supplied;
|
|
|
|
gdk_error_trap_push ();
|
|
|
|
socket->request_width = 1;
|
|
socket->request_height = 1;
|
|
|
|
if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window),
|
|
GDK_WINDOW_XWINDOW (socket->plug_window),
|
|
&hints, &supplied))
|
|
{
|
|
if (hints.flags & PMinSize)
|
|
{
|
|
socket->request_width = MAX (hints.min_width, 1);
|
|
socket->request_height = MAX (hints.min_height, 1);
|
|
}
|
|
else if (hints.flags & PBaseSize)
|
|
{
|
|
socket->request_width = MAX (hints.base_width, 1);
|
|
socket->request_height = MAX (hints.base_height, 1);
|
|
}
|
|
}
|
|
socket->have_size = TRUE;
|
|
|
|
gdk_error_trap_pop ();
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_send_key_event (GtkSocket *socket,
|
|
GdkEvent *gdk_event,
|
|
gboolean mask_key_presses)
|
|
{
|
|
XKeyEvent xkey;
|
|
GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window);
|
|
|
|
memset (&xkey, 0, sizeof (xkey));
|
|
xkey.type = (gdk_event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
|
|
xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
|
|
xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
|
|
xkey.subwindow = None;
|
|
xkey.time = gdk_event->key.time;
|
|
xkey.x = 0;
|
|
xkey.y = 0;
|
|
xkey.x_root = 0;
|
|
xkey.y_root = 0;
|
|
xkey.state = gdk_event->key.state;
|
|
xkey.keycode = gdk_event->key.hardware_keycode;
|
|
xkey.same_screen = True;/* FIXME ? */
|
|
|
|
gdk_error_trap_push ();
|
|
XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
|
|
GDK_WINDOW_XWINDOW (socket->plug_window),
|
|
False,
|
|
(mask_key_presses ? KeyPressMask : NoEventMask),
|
|
(XEvent *)&xkey);
|
|
gdk_display_sync (gdk_screen_get_display (screen));
|
|
gdk_error_trap_pop ();
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_focus_change (GtkSocket *socket,
|
|
gboolean focus_in)
|
|
{
|
|
if (focus_in)
|
|
_gtk_xembed_send_focus_message (socket->plug_window,
|
|
XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
|
|
else
|
|
_gtk_xembed_send_message (socket->plug_window,
|
|
XEMBED_FOCUS_OUT, 0, 0, 0);
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_update_active (GtkSocket *socket,
|
|
gboolean active)
|
|
{
|
|
_gtk_xembed_send_message (socket->plug_window,
|
|
active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
|
|
0, 0, 0);
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_update_modality (GtkSocket *socket,
|
|
gboolean modality)
|
|
{
|
|
_gtk_xembed_send_message (socket->plug_window,
|
|
modality ? XEMBED_MODALITY_ON : XEMBED_MODALITY_OFF,
|
|
0, 0, 0);
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_focus (GtkSocket *socket,
|
|
GtkDirectionType direction)
|
|
{
|
|
gint detail = -1;
|
|
|
|
switch (direction)
|
|
{
|
|
case GTK_DIR_UP:
|
|
case GTK_DIR_LEFT:
|
|
case GTK_DIR_TAB_BACKWARD:
|
|
detail = XEMBED_FOCUS_LAST;
|
|
break;
|
|
case GTK_DIR_DOWN:
|
|
case GTK_DIR_RIGHT:
|
|
case GTK_DIR_TAB_FORWARD:
|
|
detail = XEMBED_FOCUS_FIRST;
|
|
break;
|
|
}
|
|
|
|
_gtk_xembed_send_focus_message (socket->plug_window, XEMBED_FOCUS_IN, detail);
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_send_configure_event (GtkSocket *socket)
|
|
{
|
|
XConfigureEvent xconfigure;
|
|
gint x, y;
|
|
|
|
g_return_if_fail (socket->plug_window != NULL);
|
|
|
|
memset (&xconfigure, 0, sizeof (xconfigure));
|
|
xconfigure.type = ConfigureNotify;
|
|
|
|
xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
|
|
xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
|
|
|
|
/* The ICCCM says that synthetic events should have root relative
|
|
* coordinates. We still aren't really ICCCM compliant, since
|
|
* we don't send events when the real toplevel is moved.
|
|
*/
|
|
gdk_error_trap_push ();
|
|
gdk_window_get_origin (socket->plug_window, &x, &y);
|
|
gdk_error_trap_pop ();
|
|
|
|
xconfigure.x = x;
|
|
xconfigure.y = y;
|
|
xconfigure.width = GTK_WIDGET(socket)->allocation.width;
|
|
xconfigure.height = GTK_WIDGET(socket)->allocation.height;
|
|
|
|
xconfigure.border_width = 0;
|
|
xconfigure.above = None;
|
|
xconfigure.override_redirect = False;
|
|
|
|
gdk_error_trap_push ();
|
|
XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
|
|
GDK_WINDOW_XWINDOW (socket->plug_window),
|
|
False, NoEventMask, (XEvent *)&xconfigure);
|
|
gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket)));
|
|
gdk_error_trap_pop ();
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_select_plug_window_input (GtkSocket *socket)
|
|
{
|
|
XSelectInput (GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (socket))),
|
|
GDK_WINDOW_XWINDOW (socket->plug_window),
|
|
StructureNotifyMask | PropertyChangeMask);
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_embed_get_info (GtkSocket *socket)
|
|
{
|
|
unsigned long version;
|
|
unsigned long flags;
|
|
|
|
socket->xembed_version = -1;
|
|
if (xembed_get_info (socket->plug_window, &version, &flags))
|
|
{
|
|
socket->xembed_version = MIN (GTK_XEMBED_PROTOCOL_VERSION, version);
|
|
socket->is_mapped = (flags & XEMBED_MAPPED) != 0;
|
|
}
|
|
else
|
|
{
|
|
/* FIXME, we should probably actually check the state before we started */
|
|
socket->is_mapped = TRUE;
|
|
}
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_embed_notify (GtkSocket *socket)
|
|
{
|
|
#ifdef HAVE_XFIXES
|
|
GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (socket));
|
|
|
|
XFixesChangeSaveSet (GDK_DISPLAY_XDISPLAY (display),
|
|
GDK_WINDOW_XWINDOW (socket->plug_window),
|
|
SetModeInsert, SaveSetRoot, SaveSetUnmap);
|
|
#endif
|
|
_gtk_xembed_send_message (socket->plug_window,
|
|
XEMBED_EMBEDDED_NOTIFY, 0,
|
|
GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window),
|
|
socket->xembed_version);
|
|
}
|
|
|
|
static gboolean
|
|
xembed_get_info (GdkWindow *window,
|
|
unsigned long *version,
|
|
unsigned long *flags)
|
|
{
|
|
GdkDisplay *display = gdk_drawable_get_display (window);
|
|
Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
|
|
Atom type;
|
|
int format;
|
|
unsigned long nitems, bytes_after;
|
|
unsigned char *data;
|
|
unsigned long *data_long;
|
|
int status;
|
|
|
|
gdk_error_trap_push();
|
|
status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
|
|
GDK_WINDOW_XWINDOW (window),
|
|
xembed_info_atom,
|
|
0, 2, False,
|
|
xembed_info_atom, &type, &format,
|
|
&nitems, &bytes_after, &data);
|
|
gdk_error_trap_pop();
|
|
|
|
if (status != Success)
|
|
return FALSE; /* Window vanished? */
|
|
|
|
if (type == None) /* No info property */
|
|
return FALSE;
|
|
|
|
if (type != xembed_info_atom)
|
|
{
|
|
g_warning ("_XEMBED_INFO property has wrong type\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (nitems < 2)
|
|
{
|
|
g_warning ("_XEMBED_INFO too short\n");
|
|
XFree (data);
|
|
return FALSE;
|
|
}
|
|
|
|
data_long = (unsigned long *)data;
|
|
if (version)
|
|
*version = data_long[0];
|
|
if (flags)
|
|
*flags = data_long[1] & XEMBED_MAPPED;
|
|
|
|
XFree (data);
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
_gtk_socket_windowing_embed_get_focus_wrapped (void)
|
|
{
|
|
return _gtk_xembed_get_focus_wrapped ();
|
|
}
|
|
|
|
void
|
|
_gtk_socket_windowing_embed_set_focus_wrapped (void)
|
|
{
|
|
_gtk_xembed_set_focus_wrapped ();
|
|
}
|
|
|
|
static void
|
|
handle_xembed_message (GtkSocket *socket,
|
|
XEmbedMessageType message,
|
|
glong detail,
|
|
glong data1,
|
|
glong data2,
|
|
guint32 time)
|
|
{
|
|
GTK_NOTE (PLUGSOCKET,
|
|
g_message ("GtkSocket: %s received", _gtk_xembed_message_name (message)));
|
|
|
|
switch (message)
|
|
{
|
|
case XEMBED_EMBEDDED_NOTIFY:
|
|
case XEMBED_WINDOW_ACTIVATE:
|
|
case XEMBED_WINDOW_DEACTIVATE:
|
|
case XEMBED_MODALITY_ON:
|
|
case XEMBED_MODALITY_OFF:
|
|
case XEMBED_FOCUS_IN:
|
|
case XEMBED_FOCUS_OUT:
|
|
g_warning ("GtkSocket: Invalid _XEMBED message %s received", _gtk_xembed_message_name (message));
|
|
break;
|
|
|
|
case XEMBED_REQUEST_FOCUS:
|
|
_gtk_socket_claim_focus (socket, TRUE);
|
|
break;
|
|
|
|
case XEMBED_FOCUS_NEXT:
|
|
case XEMBED_FOCUS_PREV:
|
|
_gtk_socket_advance_toplevel_focus (socket,
|
|
(message == XEMBED_FOCUS_NEXT ?
|
|
GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
|
|
break;
|
|
|
|
case XEMBED_GTK_GRAB_KEY:
|
|
_gtk_socket_add_grabbed_key (socket, data1, data2);
|
|
break;
|
|
case XEMBED_GTK_UNGRAB_KEY:
|
|
_gtk_socket_remove_grabbed_key (socket, data1, data2);
|
|
break;
|
|
|
|
case XEMBED_GRAB_KEY:
|
|
case XEMBED_UNGRAB_KEY:
|
|
break;
|
|
|
|
default:
|
|
GTK_NOTE (PLUGSOCKET,
|
|
g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %d", message));
|
|
break;
|
|
}
|
|
}
|
|
|
|
GdkFilterReturn
|
|
_gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent,
|
|
GdkEvent *event,
|
|
gpointer data)
|
|
{
|
|
GtkSocket *socket;
|
|
GtkWidget *widget;
|
|
GdkDisplay *display;
|
|
XEvent *xevent;
|
|
|
|
GdkFilterReturn return_val;
|
|
|
|
socket = GTK_SOCKET (data);
|
|
|
|
return_val = GDK_FILTER_CONTINUE;
|
|
|
|
if (socket->plug_widget)
|
|
return return_val;
|
|
|
|
widget = GTK_WIDGET (socket);
|
|
xevent = (XEvent *)gdk_xevent;
|
|
display = gtk_widget_get_display (widget);
|
|
|
|
switch (xevent->type)
|
|
{
|
|
case ClientMessage:
|
|
if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"))
|
|
{
|
|
_gtk_xembed_push_message (xevent);
|
|
handle_xembed_message (socket,
|
|
xevent->xclient.data.l[1],
|
|
xevent->xclient.data.l[2],
|
|
xevent->xclient.data.l[3],
|
|
xevent->xclient.data.l[4],
|
|
xevent->xclient.data.l[0]);
|
|
_gtk_xembed_pop_message ();
|
|
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
break;
|
|
|
|
case CreateNotify:
|
|
{
|
|
XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
|
|
|
|
if (!socket->plug_window)
|
|
{
|
|
_gtk_socket_add_window (socket, xcwe->window, FALSE);
|
|
|
|
if (socket->plug_window)
|
|
{
|
|
GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window created"));
|
|
}
|
|
}
|
|
|
|
return_val = GDK_FILTER_REMOVE;
|
|
|
|
break;
|
|
}
|
|
|
|
case ConfigureRequest:
|
|
{
|
|
XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
|
|
|
|
if (!socket->plug_window)
|
|
_gtk_socket_add_window (socket, xcre->window, FALSE);
|
|
|
|
if (socket->plug_window)
|
|
{
|
|
GtkSocketPrivate *private = _gtk_socket_get_private (socket);
|
|
|
|
if (xcre->value_mask & (CWWidth | CWHeight))
|
|
{
|
|
GTK_NOTE (PLUGSOCKET,
|
|
g_message ("GtkSocket - configure request: %d %d",
|
|
socket->request_width,
|
|
socket->request_height));
|
|
|
|
private->resize_count++;
|
|
gtk_widget_queue_resize (widget);
|
|
}
|
|
else if (xcre->value_mask & (CWX | CWY))
|
|
{
|
|
_gtk_socket_windowing_send_configure_event (socket);
|
|
}
|
|
/* Ignore stacking requests. */
|
|
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DestroyNotify:
|
|
{
|
|
XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
|
|
|
|
/* Note that we get destroy notifies both from SubstructureNotify on
|
|
* our window and StructureNotify on socket->plug_window
|
|
*/
|
|
if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
|
|
{
|
|
gboolean result;
|
|
|
|
GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - destroy notify"));
|
|
|
|
gdk_window_destroy_notify (socket->plug_window);
|
|
_gtk_socket_end_embedding (socket);
|
|
|
|
g_object_ref (widget);
|
|
g_signal_emit_by_name (widget, "plug-removed", &result);
|
|
if (!result)
|
|
gtk_widget_destroy (widget);
|
|
g_object_unref (widget);
|
|
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FocusIn:
|
|
if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
|
|
{
|
|
_gtk_socket_claim_focus (socket, TRUE);
|
|
}
|
|
return_val = GDK_FILTER_REMOVE;
|
|
break;
|
|
case FocusOut:
|
|
return_val = GDK_FILTER_REMOVE;
|
|
break;
|
|
case MapRequest:
|
|
if (!socket->plug_window)
|
|
{
|
|
_gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE);
|
|
}
|
|
|
|
if (socket->plug_window)
|
|
{
|
|
GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - Map Request"));
|
|
|
|
_gtk_socket_handle_map_request (socket);
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
break;
|
|
case PropertyNotify:
|
|
if (socket->plug_window &&
|
|
xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window))
|
|
{
|
|
GdkDragProtocol protocol;
|
|
|
|
if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_NORMAL_HINTS"))
|
|
{
|
|
GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - received PropertyNotify for plug's WM_NORMAL_HINTS"));
|
|
socket->have_size = FALSE;
|
|
gtk_widget_queue_resize (widget);
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
else if ((xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "XdndAware")) ||
|
|
(xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_RECEIVER_INFO")))
|
|
{
|
|
gdk_error_trap_push ();
|
|
if (gdk_drag_get_protocol_for_display (display,
|
|
xevent->xproperty.window,
|
|
&protocol))
|
|
gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
|
|
socket->plug_window,
|
|
protocol, TRUE);
|
|
|
|
gdk_display_sync (display);
|
|
gdk_error_trap_pop ();
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"))
|
|
{
|
|
unsigned long flags;
|
|
|
|
if (xembed_get_info (socket->plug_window, NULL, &flags))
|
|
{
|
|
gboolean was_mapped = socket->is_mapped;
|
|
gboolean is_mapped = (flags & XEMBED_MAPPED) != 0;
|
|
|
|
if (was_mapped != is_mapped)
|
|
{
|
|
if (is_mapped)
|
|
_gtk_socket_handle_map_request (socket);
|
|
else
|
|
{
|
|
gdk_error_trap_push ();
|
|
gdk_window_show (socket->plug_window);
|
|
gdk_flush ();
|
|
gdk_error_trap_pop ();
|
|
|
|
_gtk_socket_unmap_notify (socket);
|
|
}
|
|
}
|
|
}
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
}
|
|
break;
|
|
case ReparentNotify:
|
|
{
|
|
XReparentEvent *xre = &xevent->xreparent;
|
|
|
|
GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - ReparentNotify received"));
|
|
if (!socket->plug_window && xre->parent == GDK_WINDOW_XWINDOW (widget->window))
|
|
{
|
|
_gtk_socket_add_window (socket, xre->window, FALSE);
|
|
|
|
if (socket->plug_window)
|
|
{
|
|
GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - window reparented"));
|
|
}
|
|
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
else
|
|
{
|
|
if (socket->plug_window && xre->window == GDK_WINDOW_XWINDOW (socket->plug_window) && xre->parent != GDK_WINDOW_XWINDOW (widget->window))
|
|
{
|
|
gboolean result;
|
|
|
|
_gtk_socket_end_embedding (socket);
|
|
|
|
g_object_ref (widget);
|
|
g_signal_emit_by_name (widget, "plug-removed", &result);
|
|
if (!result)
|
|
gtk_widget_destroy (widget);
|
|
g_object_unref (widget);
|
|
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case UnmapNotify:
|
|
if (socket->plug_window &&
|
|
xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window))
|
|
{
|
|
GTK_NOTE (PLUGSOCKET, g_message ("GtkSocket - Unmap notify"));
|
|
|
|
_gtk_socket_unmap_notify (socket);
|
|
return_val = GDK_FILTER_REMOVE;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
return return_val;
|
|
}
|