diff options
author | Owen Taylor <owt1@cornell.edu> | 1998-03-14 05:15:16 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 1998-03-14 05:15:16 +0000 |
commit | bc98ea9ce1884bdc4837579c4d226d227b425a52 (patch) | |
tree | 84872a7dc5739fb7f4af39970a46fd760477ee9d /gdk | |
parent | 294cfcdb222b75d741a318e76f7c8acd0690e807 (diff) | |
download | gdk-pixbuf-bc98ea9ce1884bdc4837579c4d226d227b425a52.tar.gz |
Don't resize windows when request is rejected by WM. Only use the resize
Sat Mar 14 00:03:34 1998 Owen Taylor <owt1@cornell.edu>
* gtk/gtkwindow.c:
Don't resize windows when request is rejected by WM.
Only use the resize count to guess whether a Configure
event was a rejection by the WM, or a move.
* gdk/gdk.c gdk/gdktypes.h:
- Don't XDestroyWindow foreign windows (If they're a child of
one of our windows, reparent them to root and send them a WM
delete event, otherwise, just delete the GTK structure.)
Handle notification of their deletion properly.
(Made foreign windows a seperate window type to do this)
* gtk/gtkobject.c (gtk_object_set_data_full):
Call the DestroyNotify when replacing the object data.
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/gdktypes.h | 4 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 112 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 112 |
3 files changed, 181 insertions, 47 deletions
diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h index 931fdf78b..bfb21a396 100644 --- a/gdk/gdktypes.h +++ b/gdk/gdktypes.h @@ -110,6 +110,7 @@ typedef void* GdkIM; * and pixmaps transparently. (ie. You shouldn't pass a * pixmap to any procedure which accepts a window with the * exception of the drawing functions). + * Foreign: A window that actually belongs to another application */ typedef enum { @@ -118,7 +119,8 @@ typedef enum GDK_WINDOW_CHILD, GDK_WINDOW_DIALOG, GDK_WINDOW_TEMP, - GDK_WINDOW_PIXMAP + GDK_WINDOW_PIXMAP, + GDK_WINDOW_FOREIGN } GdkWindowType; /* Classes of windows. diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 7cbaf4b60..4d7531844 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -414,13 +414,21 @@ gdk_window_foreign_new (guint32 anid) GdkWindow *window; GdkWindowPrivate *private; XWindowAttributes attrs; + Window root, parent; + Window *children; + guint nchildren; private = g_new (GdkWindowPrivate, 1); window = (GdkWindow*) private; XGetWindowAttributes (gdk_display, anid, &attrs); - private->parent = NULL; + /* FIXME: This is pretty expensive. Maybe the caller should supply + * the parent */ + XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren); + XFree (children); + private->parent = gdk_xid_table_lookup (parent); + private->xwindow = anid; private->xdisplay = gdk_display; private->x = attrs.x; @@ -429,15 +437,20 @@ gdk_window_foreign_new (guint32 anid) private->height = attrs.height; private->resize_count = 0; private->ref_count = 1; - if (anid == attrs.root) - private->window_type = GDK_WINDOW_ROOT; - else - private->window_type = GDK_WINDOW_TOPLEVEL; - /* the above is probably wrong, but it may not be worth the extra - X call to get it right */ - + private->window_type = GDK_WINDOW_FOREIGN; private->destroyed = FALSE; private->extension_events = 0; + + + private->dnd_drag_data_type = None; + private->dnd_drag_data_typesavail = + private->dnd_drop_data_typesavail = NULL; + private->dnd_drop_enabled = private->dnd_drag_enabled = + private->dnd_drag_accepted = private->dnd_drag_datashow = + private->dnd_drop_data_numtypesavail = + private->dnd_drag_data_numtypesavail = 0; + private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0; + private->filters = NULL; window->user_data = NULL; @@ -455,7 +468,8 @@ gdk_window_foreign_new (guint32 anid) window. */ static void -gdk_window_internal_destroy (GdkWindow *window, int xdestroy) +gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy, + gboolean our_destroy) { GdkWindowPrivate *private; GdkWindowPrivate *temp_private; @@ -473,23 +487,28 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy) case GDK_WINDOW_CHILD: case GDK_WINDOW_DIALOG: case GDK_WINDOW_TEMP: + case GDK_WINDOW_FOREIGN: if (!private->destroyed) { - children = gdk_window_get_children (window); - tmp = children; - - while (tmp) + if (private->window_type != GDK_WINDOW_FOREIGN) { - temp_window = tmp->data; - tmp = tmp->next; - - temp_private = (GdkWindowPrivate*) temp_window; - if (temp_private) - gdk_window_internal_destroy (temp_window, FALSE); + children = gdk_window_get_children (window); + tmp = children; + + while (tmp) + { + temp_window = tmp->data; + tmp = tmp->next; + + temp_private = (GdkWindowPrivate*) temp_window; + if (temp_private) + gdk_window_internal_destroy (temp_window, FALSE, + our_destroy); + } + + g_list_free (children); } - g_list_free (children); - if (private->extension_events != 0) gdk_input_window_destroy (window); @@ -504,8 +523,47 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy) private->dnd_drop_data_typesavail = NULL; } - if (xdestroy) + if (private->filters) + { + tmp = private->filters; + + while (tmp) + { + g_free (tmp->data); + tmp = tmp->next; + } + + g_list_free (private->filters); + private->filters = NULL; + } + + if (private->window_type == GDK_WINDOW_FOREIGN) + { + if (our_destroy && (private->parent != NULL)) + { + /* It's somebody elses window, but in our heirarchy, + * so reparent it to the root window, and then send + * it a delete event, as if we were a WM + */ + XClientMessageEvent xevent; + + gdk_window_hide (window); + gdk_window_reparent (window, NULL, 0, 0); + + xevent.type = ClientMessage; + xevent.window = private->xwindow; + xevent.message_type = gdk_wm_protocols; + xevent.format = 32; + xevent.data.l[0] = gdk_wm_delete_window; + xevent.data.l[1] = CurrentTime; + + XSendEvent (private->xdisplay, private->xwindow, + False, 0, (XEvent *)&xevent); + } + } + else if (xdestroy) XDestroyWindow (private->xdisplay, private->xwindow); + private->destroyed = TRUE; } break; @@ -526,7 +584,7 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy) void gdk_window_destroy (GdkWindow *window) { - gdk_window_internal_destroy (window, TRUE); + gdk_window_internal_destroy (window, TRUE, TRUE); gdk_window_unref (window); } @@ -541,6 +599,14 @@ gdk_window_destroy_notify (GdkWindow *window) private = (GdkWindowPrivate*) window; + if (!private->destroyed) + { + if (private->window_type == GDK_WINDOW_FOREIGN) + gdk_window_internal_destroy (window, FALSE, FALSE); + else + g_warning ("Window %#lx unexpectedly destroyed", private->xwindow); + } + gdk_xid_table_remove (private->xwindow); gdk_window_unref (window); } diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 7cbaf4b60..4d7531844 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -414,13 +414,21 @@ gdk_window_foreign_new (guint32 anid) GdkWindow *window; GdkWindowPrivate *private; XWindowAttributes attrs; + Window root, parent; + Window *children; + guint nchildren; private = g_new (GdkWindowPrivate, 1); window = (GdkWindow*) private; XGetWindowAttributes (gdk_display, anid, &attrs); - private->parent = NULL; + /* FIXME: This is pretty expensive. Maybe the caller should supply + * the parent */ + XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren); + XFree (children); + private->parent = gdk_xid_table_lookup (parent); + private->xwindow = anid; private->xdisplay = gdk_display; private->x = attrs.x; @@ -429,15 +437,20 @@ gdk_window_foreign_new (guint32 anid) private->height = attrs.height; private->resize_count = 0; private->ref_count = 1; - if (anid == attrs.root) - private->window_type = GDK_WINDOW_ROOT; - else - private->window_type = GDK_WINDOW_TOPLEVEL; - /* the above is probably wrong, but it may not be worth the extra - X call to get it right */ - + private->window_type = GDK_WINDOW_FOREIGN; private->destroyed = FALSE; private->extension_events = 0; + + + private->dnd_drag_data_type = None; + private->dnd_drag_data_typesavail = + private->dnd_drop_data_typesavail = NULL; + private->dnd_drop_enabled = private->dnd_drag_enabled = + private->dnd_drag_accepted = private->dnd_drag_datashow = + private->dnd_drop_data_numtypesavail = + private->dnd_drag_data_numtypesavail = 0; + private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0; + private->filters = NULL; window->user_data = NULL; @@ -455,7 +468,8 @@ gdk_window_foreign_new (guint32 anid) window. */ static void -gdk_window_internal_destroy (GdkWindow *window, int xdestroy) +gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy, + gboolean our_destroy) { GdkWindowPrivate *private; GdkWindowPrivate *temp_private; @@ -473,23 +487,28 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy) case GDK_WINDOW_CHILD: case GDK_WINDOW_DIALOG: case GDK_WINDOW_TEMP: + case GDK_WINDOW_FOREIGN: if (!private->destroyed) { - children = gdk_window_get_children (window); - tmp = children; - - while (tmp) + if (private->window_type != GDK_WINDOW_FOREIGN) { - temp_window = tmp->data; - tmp = tmp->next; - - temp_private = (GdkWindowPrivate*) temp_window; - if (temp_private) - gdk_window_internal_destroy (temp_window, FALSE); + children = gdk_window_get_children (window); + tmp = children; + + while (tmp) + { + temp_window = tmp->data; + tmp = tmp->next; + + temp_private = (GdkWindowPrivate*) temp_window; + if (temp_private) + gdk_window_internal_destroy (temp_window, FALSE, + our_destroy); + } + + g_list_free (children); } - g_list_free (children); - if (private->extension_events != 0) gdk_input_window_destroy (window); @@ -504,8 +523,47 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy) private->dnd_drop_data_typesavail = NULL; } - if (xdestroy) + if (private->filters) + { + tmp = private->filters; + + while (tmp) + { + g_free (tmp->data); + tmp = tmp->next; + } + + g_list_free (private->filters); + private->filters = NULL; + } + + if (private->window_type == GDK_WINDOW_FOREIGN) + { + if (our_destroy && (private->parent != NULL)) + { + /* It's somebody elses window, but in our heirarchy, + * so reparent it to the root window, and then send + * it a delete event, as if we were a WM + */ + XClientMessageEvent xevent; + + gdk_window_hide (window); + gdk_window_reparent (window, NULL, 0, 0); + + xevent.type = ClientMessage; + xevent.window = private->xwindow; + xevent.message_type = gdk_wm_protocols; + xevent.format = 32; + xevent.data.l[0] = gdk_wm_delete_window; + xevent.data.l[1] = CurrentTime; + + XSendEvent (private->xdisplay, private->xwindow, + False, 0, (XEvent *)&xevent); + } + } + else if (xdestroy) XDestroyWindow (private->xdisplay, private->xwindow); + private->destroyed = TRUE; } break; @@ -526,7 +584,7 @@ gdk_window_internal_destroy (GdkWindow *window, int xdestroy) void gdk_window_destroy (GdkWindow *window) { - gdk_window_internal_destroy (window, TRUE); + gdk_window_internal_destroy (window, TRUE, TRUE); gdk_window_unref (window); } @@ -541,6 +599,14 @@ gdk_window_destroy_notify (GdkWindow *window) private = (GdkWindowPrivate*) window; + if (!private->destroyed) + { + if (private->window_type == GDK_WINDOW_FOREIGN) + gdk_window_internal_destroy (window, FALSE, FALSE); + else + g_warning ("Window %#lx unexpectedly destroyed", private->xwindow); + } + gdk_xid_table_remove (private->xwindow); gdk_window_unref (window); } |