diff options
author | Owen Taylor <otaylor@redhat.com> | 2004-03-13 18:27:56 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2004-03-13 18:27:56 +0000 |
commit | ef5915da35267558c5840157b45baa0d45c782a7 (patch) | |
tree | 3ac1509f734c0cc6d962a39e83cdaac9cd30cb62 /gdk | |
parent | fadaa651457f9f0adc282f65caa42e70cb386609 (diff) | |
download | gtk+-ef5915da35267558c5840157b45baa0d45c782a7.tar.gz |
Make this a total no-op when the new or old parent is destroyed. (#134230,
Sat Mar 13 12:17:16 2004 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkwindow-x11.c (gdk_window_reparent): Make
this a total no-op when the new or old parent is
destroyed. (#134230, patch from Soeren Sandmann)
* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy):
For foreign windows in our heirarchy, call
_gdk_windowing_window_destroy_foreign (window) and skip
all the normal destruction logic.
* gdk/x11/gdkwindow-x11.c gdk/win32/gdkwindow-win32.c:
Move code to request destruction of a foreign window
code into a separate _gdk_windowing_window_destroy_foreign().
* gdk/x11/gdkwindow-x11.c (gdk_window_impl_x11_finalize):
Call GDK_WINDOW_DISPLAY() on the wrapper not on the
impl. (Also from Soeren's patch)
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/gdkinternals.h | 7 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 54 | ||||
-rw-r--r-- | gdk/win32/gdkwindow-win32.c | 40 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 88 |
4 files changed, 114 insertions, 75 deletions
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index 6f4c539424..f9d3c02798 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -306,6 +306,13 @@ void _gdk_windowing_window_destroy (GdkWindow *window, gboolean recursing, gboolean foreign_destroy); +/* Called when gdk_window_destroy() is called on a foreign window + * or an ancestor of the foreign window. It should generally reparent + * the window out of it's current heirarchy, hide it, and then + * send a message to the owner requesting that the window be destroyed. + */ +void _gdk_windowing_window_destroy_foreign (GdkWindow *window); + void _gdk_windowing_display_set_sm_client_id (GdkDisplay *display, const gchar *sm_client_id); diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 4df74dd6df..7987e650a3 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -278,6 +278,23 @@ gdk_window_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +window_remove_filters (GdkWindow *window) +{ + GdkWindowObject *obj = (GdkWindowObject*) window; + + if (obj->filters) + { + GList *tmp_list; + + for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next) + g_free (tmp_list->data); + + g_list_free (obj->filters); + obj->filters = NULL; + } +} + /** * _gdk_window_destroy_hierarchy: * @window: a #GdkWindow @@ -309,6 +326,9 @@ _gdk_window_destroy_hierarchy (GdkWindow *window, private = (GdkWindowObject*) window; + if (GDK_WINDOW_DESTROYED (window)) + return; + switch (GDK_WINDOW_TYPE (window)) { case GDK_WINDOW_TOPLEVEL: @@ -316,7 +336,25 @@ _gdk_window_destroy_hierarchy (GdkWindow *window, case GDK_WINDOW_DIALOG: case GDK_WINDOW_TEMP: case GDK_WINDOW_FOREIGN: - if (!GDK_WINDOW_DESTROYED (window)) + if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy) + { + /* Logically, it probably makes more sense to send + * a "destroy yourself" message to the foreign window + * whether or not it's in our heirarchy; but for historical + * reasons, we only send "destroy yourself" messages to + * foreign windows in our heirarchy. + */ + if (private->parent) + _gdk_windowing_window_destroy_foreign (window); + + /* Also for historical reasons, we remove any filters + * on a foreign window when it or a parent is destroyed; + * this likely causes problems if two separate portions + * of code are maintaining filter lists on a foreign window. + */ + window_remove_filters (window); + } + else { private->state |= GDK_WINDOW_STATE_WITHDRAWN; @@ -363,19 +401,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window, private->parent = NULL; private->destroyed = TRUE; - if (private->filters) - { - tmp = private->filters; - - while (tmp) - { - g_free (tmp->data); - tmp = tmp->next; - } - - g_list_free (private->filters); - private->filters = NULL; - } + window_remove_filters (window); gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL); } diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c index 424a543313..958df71c91 100644 --- a/gdk/win32/gdkwindow-win32.c +++ b/gdk/win32/gdkwindow-win32.c @@ -810,32 +810,32 @@ _gdk_windowing_window_destroy (GdkWindow *window, if (private->extension_events != 0) _gdk_input_window_destroy (window); - if (private->window_type == GDK_WINDOW_FOREIGN) - { - if (!foreign_destroy && (private->parent != NULL)) - { - /* It's somebody else's window, but in our hierarchy, - * so reparent it to the root window, and then call - * DestroyWindow() on it. - */ - gdk_window_hide (window); - gdk_window_reparent (window, NULL, 0, 0); - - /* Is this too drastic? Many (most?) applications - * quit if any window receives WM_QUIT I think. - * OTOH, I don't think foreign windows are much - * used, so the question is maybe academic. - */ - PostMessage (GDK_WINDOW_HWND (window), WM_QUIT, 0, 0); - } - } - else if (!recursing && !foreign_destroy) + + if (!recursing && !foreign_destroy) { private->destroyed = TRUE; DestroyWindow (GDK_WINDOW_HWND (window)); } } +void +_gdk_windowing_window_destroy_foreign (GdkWindow *window) +{ + /* It's somebody else's window, but in our hierarchy, + * so reparent it to the root window, and then call + * DestroyWindow() on it. + */ + gdk_window_hide (window); + gdk_window_reparent (window, NULL, 0, 0); + + /* Is this too drastic? Many (most?) applications + * quit if any window receives WM_QUIT I think. + * OTOH, I don't think foreign windows are much + * used, so the question is maybe academic. + */ + PostMessage (GDK_WINDOW_HWND (window), WM_QUIT, 0, 0); +} + /* This function is called when the window really gone. */ void diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index a4a26d14b6..c594444845 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -204,9 +204,11 @@ gdk_window_impl_x11_finalize (GObject *object) if (!GDK_WINDOW_DESTROYED (wrapper)) { - _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (object), draw_impl->xid); + GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper); + + _gdk_xid_table_remove (display, draw_impl->xid); if (window_impl->toplevel && window_impl->toplevel->focus_window) - _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (object), window_impl->toplevel->focus_window); + _gdk_xid_table_remove (display, window_impl->toplevel->focus_window); } if (window_impl->toplevel) @@ -937,45 +939,44 @@ _gdk_windowing_window_destroy (GdkWindow *window, if (draw_impl->xft_draw) XftDrawDestroy (draw_impl->xft_draw); - if (private->window_type == GDK_WINDOW_FOREIGN) - { - if (!foreign_destroy && (private->parent != NULL)) - { - /* It's somebody else's 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_error_trap_push (); - gdk_window_hide (window); - gdk_window_reparent (window, NULL, 0, 0); - - xevent.type = ClientMessage; - xevent.window = GDK_WINDOW_XID (window); - xevent.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), - "WM_PROTOCOLS"); - xevent.format = 32; - xevent.data.l[0] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), - "WM_DELETE_WINDOW"); - xevent.data.l[1] = CurrentTime; - xevent.data.l[2] = 0; - xevent.data.l[3] = 0; - xevent.data.l[4] = 0; - - XSendEvent (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - False, 0, (XEvent *)&xevent); - gdk_display_sync (GDK_WINDOW_DISPLAY (window)); - gdk_error_trap_pop (); - } - } - else if (!recursing && !foreign_destroy) + if (!recursing && !foreign_destroy) { XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window)); } } +void +_gdk_windowing_window_destroy_foreign (GdkWindow *window) +{ + /* It's somebody else's 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_error_trap_push (); + gdk_window_hide (window); + gdk_window_reparent (window, NULL, 0, 0); + + xevent.type = ClientMessage; + xevent.window = GDK_WINDOW_XID (window); + xevent.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), + "WM_PROTOCOLS"); + xevent.format = 32; + xevent.data.l[0] = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window), + "WM_DELETE_WINDOW"); + xevent.data.l[1] = CurrentTime; + xevent.data.l[2] = 0; + xevent.data.l[3] = 0; + xevent.data.l[4] = 0; + + XSendEvent (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + False, 0, (XEvent *)&xevent); + gdk_display_sync (GDK_WINDOW_DISPLAY (window)); + gdk_error_trap_pop (); +} + /* This function is called when the XWindow is really gone. */ void @@ -1502,6 +1503,12 @@ gdk_window_reparent (GdkWindow *window, g_return_if_fail (GDK_IS_WINDOW (window)); g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent)); g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT); + + if (GDK_WINDOW_DESTROYED (window) || + (new_parent && GDK_WINDOW_DESTROYED (new_parent))) + { + return; + } if (!new_parent) new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window)); @@ -1513,11 +1520,10 @@ gdk_window_reparent (GdkWindow *window, parent_private = (GdkWindowObject*) new_parent; impl = GDK_WINDOW_IMPL_X11 (window_private->impl); - if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (new_parent)) - XReparentWindow (GDK_WINDOW_XDISPLAY (window), - GDK_WINDOW_XID (window), - GDK_WINDOW_XID (new_parent), - x, y); + XReparentWindow (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + GDK_WINDOW_XID (new_parent), + x, y); window_private->x = x; window_private->y = y; |