Updated unexpected window destruction patch.
- From: Nat Friedman <nat nat org>
- To: gtk-devel-list redhat com
- Cc: Owen Taylor <otaylor redhat com>, Miguel de Icaza <miguel nuclecu unam mx>
- Subject: Updated unexpected window destruction patch.
- Date: 24 Aug 1999 14:11:37 -0400
Hello guys,
Here is my new window destruction patch, updated to reflect
everyone's suggestions. It really improves the robustness of Bonobo
components dramatically, so it would be a boon for us if it could make
it into the next Gtk 1.2 distribution. If there's anything I can do
to facilitate this, please let me know.
Best,
Nat
Sun Aug 22 19:08:28 1999 Nat Friedman <nat@nat.org>
* gtk/gtkplug.c (gtk_plug_class_init): Override the widget class
unrealize function with gtk_plug_unrealize. Store a new
GtkWindowClass in a static global, parent_class.
(gtk_plug_construct): Store the widget pointer in the
socket_window's user data.
(gtk_plug_unrealize): New unrealize handler for GtkPlug.
* gdk/gdkwindow.c (gdk_window_destroy_notify_new):
gdk_window_destroy_notify was renamed to this function to maintain
binary compatibility. If a window is unexpectedly destroyed,
rewrite the DestroyNotify event to occur on the window's first
foreign ancestor, if it has one.
(gdk_window_destroy_notify): Call gdk_window_destroy_notify_new.
* gdk/gdkevents.c (gdk_event_translate): Pass the event to
gdk_window_destroy_notify_new.
Index: gdk/gdkevents.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkevents.c,v
retrieving revision 1.20.2.6
diff -u -r1.20.2.6 gdkevents.c
--- gdk/gdkevents.c 1999/08/20 02:18:15 1.20.2.6
+++ gdk/gdkevents.c 1999/08/24 18:03:44
@@ -1622,7 +1622,8 @@
return_val = window_private && !window_private->destroyed;
if(window && window_private->xwindow != GDK_ROOT_WINDOW())
- gdk_window_destroy_notify (window);
+ gdk_window_destroy_notify_new (window, event);
+
break;
case UnmapNotify:
Index: gdk/gdkprivate.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkprivate.h,v
retrieving revision 1.36
diff -u -r1.36 gdkprivate.h
--- gdk/gdkprivate.h 1999/02/24 07:33:09 1.36
+++ gdk/gdkprivate.h 1999/08/24 18:03:44
@@ -241,6 +241,8 @@
void gdk_window_add_colormap_windows (GdkWindow *window);
void gdk_window_destroy_notify (GdkWindow *window);
+/* Take note: gdk_window_destroy_notify_new will be removed in 1.3 */
+void gdk_window_destroy_notify_new (GdkWindow *window, GdkEvent *event);
void gdk_xid_table_insert (XID *xid,
gpointer data);
Index: gdk/gdkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.c,v
retrieving revision 1.80.2.5
diff -u -r1.80.2.5 gdkwindow.c
--- gdk/gdkwindow.c 1999/08/18 20:21:06 1.80.2.5
+++ gdk/gdkwindow.c 1999/08/24 18:03:44
@@ -687,12 +687,11 @@
}
/* This function is called when the XWindow is really gone. */
-
void
-gdk_window_destroy_notify (GdkWindow *window)
+gdk_window_destroy_notify_new (GdkWindow *window, GdkEvent *event)
{
GdkWindowPrivate *private;
-
+
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
@@ -701,12 +700,50 @@
{
if (private->window_type == GDK_WINDOW_FOREIGN)
gdk_window_internal_destroy (window, FALSE, FALSE);
- else
+ else {
+ GdkWindowPrivate *parent;
+
g_warning ("GdkWindow %#lx unexpectedly destroyed", private->xwindow);
+
+ gdk_window_internal_destroy (window, FALSE, FALSE);
+
+ /*
+ * A window has been unexpectedly destroyed by the X server.
+ *
+ * In the case where a foreign, reparented window (such as is
+ * used by GtkPlug) is destroyed by the death of the client
+ * which created it, the X server will recursively destroy all
+ * of that window's subwindows. In what is effectively a
+ * random order. So what we do here is to walk up the window
+ * tree until we encounter the first foreign window, and
+ * rewrite the event to occur on that window. That way, the
+ * first widget to be destroyed will be the GtkPlug, and its
+ * subwidgets can be killed politely.
+ *
+ * If there is no foreign ancestral window, we don't rewrite
+ * the event.
+ */
+ parent = private;
+ while (parent != NULL && parent->window_type != GDK_WINDOW_FOREIGN)
+ parent = (GdkWindowPrivate *) parent->parent;
+
+ if (parent != NULL)
+ event->any.window = (GdkWindow *) parent;
+ }
}
gdk_xid_table_remove (private->xwindow);
gdk_window_unref (window);
+}
+
+/*
+ * FIXME: gdk_window_destroy_notify() and
+ * gdk_window_destroy_notify_new() should be consolidated in 1.3.
+ */
+void
+gdk_window_destroy_notify (GdkWindow *window)
+{
+ gdk_window_destroy_notify_new (window, NULL);
}
GdkWindow*
cvs server: Diffing gtk
Index: gtk/gtkplug.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkplug.c,v
retrieving revision 1.6
diff -u -r1.6 gtkplug.c
--- gtk/gtkplug.c 1999/02/24 07:35:47 1.6
+++ gtk/gtkplug.c 1999/08/24 18:03:44
@@ -29,10 +29,13 @@
#include "gdk/gdkkeysyms.h"
#include "gtkplug.h"
+static GtkWindowClass *parent_class = NULL;
+
static void gtk_plug_class_init (GtkPlugClass *klass);
static void gtk_plug_init (GtkPlug *plug);
static void gtk_plug_realize (GtkWidget *widget);
+static void gtk_plug_unrealize (GtkWidget *widget);
static gint gtk_plug_key_press_event (GtkWidget *widget,
GdkEventKey *event);
static void gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event);
@@ -76,8 +79,10 @@
widget_class = (GtkWidgetClass *)class;
window_class = (GtkWindowClass *)class;
+ parent_class = gtk_type_new (GTK_TYPE_WINDOW);
widget_class->realize = gtk_plug_realize;
+ widget_class->unrealize = gtk_plug_unrealize;
widget_class->key_press_event = gtk_plug_key_press_event;
widget_class->focus_in_event = gtk_plug_focus_in_event;
widget_class->focus_out_event = gtk_plug_focus_out_event;
@@ -105,6 +110,7 @@
if (plug->socket_window == NULL)
{
plug->socket_window = gdk_window_foreign_new (socket_id);
+ gdk_window_set_user_data (plug->socket_window, plug);
plug->same_app = FALSE;
}
}
@@ -117,6 +123,29 @@
plug = GTK_PLUG (gtk_type_new (gtk_plug_get_type ()));
gtk_plug_construct (plug, socket_id);
return GTK_WIDGET (plug);
+}
+
+static void
+gtk_plug_unrealize (GtkWidget *widget)
+{
+ GtkPlug *plug;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_PLUG (widget));
+
+ plug = GTK_PLUG (widget);
+
+ if (plug->socket_window != NULL)
+ {
+ gdk_window_set_user_data (plug->socket_window, NULL);
+ gdk_window_destroy (plug->socket_window);
+
+ gdk_window_set_user_data (widget->window, NULL);
+ gdk_window_destroy (widget->window);
+ }
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]