diff options
-rw-r--r-- | ChangeLog | 56 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 56 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 56 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 56 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 56 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 56 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 56 | ||||
-rw-r--r-- | gdk/x11/gdkevents-x11.c | 22 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 89 | ||||
-rw-r--r-- | gtk/gtkdnd.c | 65 | ||||
-rw-r--r-- | gtk/gtkentry.c | 2 | ||||
-rw-r--r-- | gtk/gtklabel.c | 10 | ||||
-rw-r--r-- | gtk/gtkmenubar.c | 4 | ||||
-rw-r--r-- | gtk/gtkplug.c | 237 | ||||
-rw-r--r-- | gtk/gtkplug.h | 11 | ||||
-rw-r--r-- | gtk/gtksocket.c | 211 | ||||
-rw-r--r-- | gtk/gtksocket.h | 12 | ||||
-rw-r--r-- | gtk/gtktreeviewcolumn.c | 6 | ||||
-rw-r--r-- | gtk/gtkwidget.c | 57 | ||||
-rw-r--r-- | gtk/gtkwidget.h | 6 | ||||
-rw-r--r-- | tests/testsocket.c | 137 |
21 files changed, 1076 insertions, 185 deletions
@@ -1,3 +1,59 @@ +Wed Jul 4 22:35:40 2001 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklabel.c gtk/gtkmenubar.c gtk/gtktreeviewcolumn.c + gtk/gtkwidget.c: + Check GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel (widget)), + not GTK_WIDGET_GET_ANCESTOR ... see + http://mail.gnome.org/archives/gtk-devel-list/2001-July/msg00072.html. + Indicate the best practice in the docs for gtk_widget_get_toplevel(). + + * gtk/gtkwidget.[ch]: Expose a private _gtk_widget_hierarchy_changed(), + so GtkPlug can give the correct signals when transforming + from a child to a toplevel. + + * gtk/gtkdnd.c (gtk_drag_dest_hierarchy_changed): Handle + reparentation correctly. + + * gtk/gtkwidget.c (gtk_widget_propagate_hierarchy_changed): + Propagate the previous_toplevel argument down properly. + + * gtk/gtklabel.c (gtk_label_finalize): Fix unrefing + of wrong atr list. + + * gtk/gtkplug.[ch]: Add an "embedded" signal. + + * gtk/gtksocket.[ch]: Add "child_added", "child_removed" + signals. + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch]: Add + functions gtk_plug_get_id(), gtk_socket_get_id(), + to avoid the user having to worry about realization, + and gdkx.h. + + * tests/testsocket.c: Extend to try out the new signals + and gtk_plug/socket_get_id(). + + * gtk/gtklabel.c (gtk_label_set_pattern_internal): Fix + setting of underline attributes. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Ignore + DestroyNotify events from SubstructureNotifyMask + + * gdk/x11/gdkwindow-x11.c (gdk_window_reparent): + Switch GDK_WINDOW_TYPE (window) as needed. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Clean up, + allow creation of toplevel windows as children of + foreign windows. + + * gtk/gtkplug.c: Remove hacks involving changing private + fields of GdkWindow. + + * gtk/gtkplug.[ch] gtk/gtksocket.c: Work to make + exactly the same signals and notification + be emitted for local embedding as for inter-process + embedding. + 2001-07-04 James Henstridge <james@daa.com.au> * gtk/gtkliststore.h: add missing gtk_list_store_newv prototype. diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 565f2a4075..e4928ac7c3 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,59 @@ +Wed Jul 4 22:35:40 2001 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklabel.c gtk/gtkmenubar.c gtk/gtktreeviewcolumn.c + gtk/gtkwidget.c: + Check GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel (widget)), + not GTK_WIDGET_GET_ANCESTOR ... see + http://mail.gnome.org/archives/gtk-devel-list/2001-July/msg00072.html. + Indicate the best practice in the docs for gtk_widget_get_toplevel(). + + * gtk/gtkwidget.[ch]: Expose a private _gtk_widget_hierarchy_changed(), + so GtkPlug can give the correct signals when transforming + from a child to a toplevel. + + * gtk/gtkdnd.c (gtk_drag_dest_hierarchy_changed): Handle + reparentation correctly. + + * gtk/gtkwidget.c (gtk_widget_propagate_hierarchy_changed): + Propagate the previous_toplevel argument down properly. + + * gtk/gtklabel.c (gtk_label_finalize): Fix unrefing + of wrong atr list. + + * gtk/gtkplug.[ch]: Add an "embedded" signal. + + * gtk/gtksocket.[ch]: Add "child_added", "child_removed" + signals. + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch]: Add + functions gtk_plug_get_id(), gtk_socket_get_id(), + to avoid the user having to worry about realization, + and gdkx.h. + + * tests/testsocket.c: Extend to try out the new signals + and gtk_plug/socket_get_id(). + + * gtk/gtklabel.c (gtk_label_set_pattern_internal): Fix + setting of underline attributes. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Ignore + DestroyNotify events from SubstructureNotifyMask + + * gdk/x11/gdkwindow-x11.c (gdk_window_reparent): + Switch GDK_WINDOW_TYPE (window) as needed. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Clean up, + allow creation of toplevel windows as children of + foreign windows. + + * gtk/gtkplug.c: Remove hacks involving changing private + fields of GdkWindow. + + * gtk/gtkplug.[ch] gtk/gtksocket.c: Work to make + exactly the same signals and notification + be emitted for local embedding as for inter-process + embedding. + 2001-07-04 James Henstridge <james@daa.com.au> * gtk/gtkliststore.h: add missing gtk_list_store_newv prototype. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 565f2a4075..e4928ac7c3 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,59 @@ +Wed Jul 4 22:35:40 2001 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklabel.c gtk/gtkmenubar.c gtk/gtktreeviewcolumn.c + gtk/gtkwidget.c: + Check GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel (widget)), + not GTK_WIDGET_GET_ANCESTOR ... see + http://mail.gnome.org/archives/gtk-devel-list/2001-July/msg00072.html. + Indicate the best practice in the docs for gtk_widget_get_toplevel(). + + * gtk/gtkwidget.[ch]: Expose a private _gtk_widget_hierarchy_changed(), + so GtkPlug can give the correct signals when transforming + from a child to a toplevel. + + * gtk/gtkdnd.c (gtk_drag_dest_hierarchy_changed): Handle + reparentation correctly. + + * gtk/gtkwidget.c (gtk_widget_propagate_hierarchy_changed): + Propagate the previous_toplevel argument down properly. + + * gtk/gtklabel.c (gtk_label_finalize): Fix unrefing + of wrong atr list. + + * gtk/gtkplug.[ch]: Add an "embedded" signal. + + * gtk/gtksocket.[ch]: Add "child_added", "child_removed" + signals. + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch]: Add + functions gtk_plug_get_id(), gtk_socket_get_id(), + to avoid the user having to worry about realization, + and gdkx.h. + + * tests/testsocket.c: Extend to try out the new signals + and gtk_plug/socket_get_id(). + + * gtk/gtklabel.c (gtk_label_set_pattern_internal): Fix + setting of underline attributes. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Ignore + DestroyNotify events from SubstructureNotifyMask + + * gdk/x11/gdkwindow-x11.c (gdk_window_reparent): + Switch GDK_WINDOW_TYPE (window) as needed. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Clean up, + allow creation of toplevel windows as children of + foreign windows. + + * gtk/gtkplug.c: Remove hacks involving changing private + fields of GdkWindow. + + * gtk/gtkplug.[ch] gtk/gtksocket.c: Work to make + exactly the same signals and notification + be emitted for local embedding as for inter-process + embedding. + 2001-07-04 James Henstridge <james@daa.com.au> * gtk/gtkliststore.h: add missing gtk_list_store_newv prototype. diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 565f2a4075..e4928ac7c3 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,59 @@ +Wed Jul 4 22:35:40 2001 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklabel.c gtk/gtkmenubar.c gtk/gtktreeviewcolumn.c + gtk/gtkwidget.c: + Check GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel (widget)), + not GTK_WIDGET_GET_ANCESTOR ... see + http://mail.gnome.org/archives/gtk-devel-list/2001-July/msg00072.html. + Indicate the best practice in the docs for gtk_widget_get_toplevel(). + + * gtk/gtkwidget.[ch]: Expose a private _gtk_widget_hierarchy_changed(), + so GtkPlug can give the correct signals when transforming + from a child to a toplevel. + + * gtk/gtkdnd.c (gtk_drag_dest_hierarchy_changed): Handle + reparentation correctly. + + * gtk/gtkwidget.c (gtk_widget_propagate_hierarchy_changed): + Propagate the previous_toplevel argument down properly. + + * gtk/gtklabel.c (gtk_label_finalize): Fix unrefing + of wrong atr list. + + * gtk/gtkplug.[ch]: Add an "embedded" signal. + + * gtk/gtksocket.[ch]: Add "child_added", "child_removed" + signals. + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch]: Add + functions gtk_plug_get_id(), gtk_socket_get_id(), + to avoid the user having to worry about realization, + and gdkx.h. + + * tests/testsocket.c: Extend to try out the new signals + and gtk_plug/socket_get_id(). + + * gtk/gtklabel.c (gtk_label_set_pattern_internal): Fix + setting of underline attributes. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Ignore + DestroyNotify events from SubstructureNotifyMask + + * gdk/x11/gdkwindow-x11.c (gdk_window_reparent): + Switch GDK_WINDOW_TYPE (window) as needed. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Clean up, + allow creation of toplevel windows as children of + foreign windows. + + * gtk/gtkplug.c: Remove hacks involving changing private + fields of GdkWindow. + + * gtk/gtkplug.[ch] gtk/gtksocket.c: Work to make + exactly the same signals and notification + be emitted for local embedding as for inter-process + embedding. + 2001-07-04 James Henstridge <james@daa.com.au> * gtk/gtkliststore.h: add missing gtk_list_store_newv prototype. diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 565f2a4075..e4928ac7c3 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,59 @@ +Wed Jul 4 22:35:40 2001 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklabel.c gtk/gtkmenubar.c gtk/gtktreeviewcolumn.c + gtk/gtkwidget.c: + Check GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel (widget)), + not GTK_WIDGET_GET_ANCESTOR ... see + http://mail.gnome.org/archives/gtk-devel-list/2001-July/msg00072.html. + Indicate the best practice in the docs for gtk_widget_get_toplevel(). + + * gtk/gtkwidget.[ch]: Expose a private _gtk_widget_hierarchy_changed(), + so GtkPlug can give the correct signals when transforming + from a child to a toplevel. + + * gtk/gtkdnd.c (gtk_drag_dest_hierarchy_changed): Handle + reparentation correctly. + + * gtk/gtkwidget.c (gtk_widget_propagate_hierarchy_changed): + Propagate the previous_toplevel argument down properly. + + * gtk/gtklabel.c (gtk_label_finalize): Fix unrefing + of wrong atr list. + + * gtk/gtkplug.[ch]: Add an "embedded" signal. + + * gtk/gtksocket.[ch]: Add "child_added", "child_removed" + signals. + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch]: Add + functions gtk_plug_get_id(), gtk_socket_get_id(), + to avoid the user having to worry about realization, + and gdkx.h. + + * tests/testsocket.c: Extend to try out the new signals + and gtk_plug/socket_get_id(). + + * gtk/gtklabel.c (gtk_label_set_pattern_internal): Fix + setting of underline attributes. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Ignore + DestroyNotify events from SubstructureNotifyMask + + * gdk/x11/gdkwindow-x11.c (gdk_window_reparent): + Switch GDK_WINDOW_TYPE (window) as needed. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Clean up, + allow creation of toplevel windows as children of + foreign windows. + + * gtk/gtkplug.c: Remove hacks involving changing private + fields of GdkWindow. + + * gtk/gtkplug.[ch] gtk/gtksocket.c: Work to make + exactly the same signals and notification + be emitted for local embedding as for inter-process + embedding. + 2001-07-04 James Henstridge <james@daa.com.au> * gtk/gtkliststore.h: add missing gtk_list_store_newv prototype. diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 565f2a4075..e4928ac7c3 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,59 @@ +Wed Jul 4 22:35:40 2001 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklabel.c gtk/gtkmenubar.c gtk/gtktreeviewcolumn.c + gtk/gtkwidget.c: + Check GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel (widget)), + not GTK_WIDGET_GET_ANCESTOR ... see + http://mail.gnome.org/archives/gtk-devel-list/2001-July/msg00072.html. + Indicate the best practice in the docs for gtk_widget_get_toplevel(). + + * gtk/gtkwidget.[ch]: Expose a private _gtk_widget_hierarchy_changed(), + so GtkPlug can give the correct signals when transforming + from a child to a toplevel. + + * gtk/gtkdnd.c (gtk_drag_dest_hierarchy_changed): Handle + reparentation correctly. + + * gtk/gtkwidget.c (gtk_widget_propagate_hierarchy_changed): + Propagate the previous_toplevel argument down properly. + + * gtk/gtklabel.c (gtk_label_finalize): Fix unrefing + of wrong atr list. + + * gtk/gtkplug.[ch]: Add an "embedded" signal. + + * gtk/gtksocket.[ch]: Add "child_added", "child_removed" + signals. + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch]: Add + functions gtk_plug_get_id(), gtk_socket_get_id(), + to avoid the user having to worry about realization, + and gdkx.h. + + * tests/testsocket.c: Extend to try out the new signals + and gtk_plug/socket_get_id(). + + * gtk/gtklabel.c (gtk_label_set_pattern_internal): Fix + setting of underline attributes. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Ignore + DestroyNotify events from SubstructureNotifyMask + + * gdk/x11/gdkwindow-x11.c (gdk_window_reparent): + Switch GDK_WINDOW_TYPE (window) as needed. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Clean up, + allow creation of toplevel windows as children of + foreign windows. + + * gtk/gtkplug.c: Remove hacks involving changing private + fields of GdkWindow. + + * gtk/gtkplug.[ch] gtk/gtksocket.c: Work to make + exactly the same signals and notification + be emitted for local embedding as for inter-process + embedding. + 2001-07-04 James Henstridge <james@daa.com.au> * gtk/gtkliststore.h: add missing gtk_list_store_newv prototype. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 565f2a4075..e4928ac7c3 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,59 @@ +Wed Jul 4 22:35:40 2001 Owen Taylor <otaylor@redhat.com> + + * gtk/gtklabel.c gtk/gtkmenubar.c gtk/gtktreeviewcolumn.c + gtk/gtkwidget.c: + Check GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel (widget)), + not GTK_WIDGET_GET_ANCESTOR ... see + http://mail.gnome.org/archives/gtk-devel-list/2001-July/msg00072.html. + Indicate the best practice in the docs for gtk_widget_get_toplevel(). + + * gtk/gtkwidget.[ch]: Expose a private _gtk_widget_hierarchy_changed(), + so GtkPlug can give the correct signals when transforming + from a child to a toplevel. + + * gtk/gtkdnd.c (gtk_drag_dest_hierarchy_changed): Handle + reparentation correctly. + + * gtk/gtkwidget.c (gtk_widget_propagate_hierarchy_changed): + Propagate the previous_toplevel argument down properly. + + * gtk/gtklabel.c (gtk_label_finalize): Fix unrefing + of wrong atr list. + + * gtk/gtkplug.[ch]: Add an "embedded" signal. + + * gtk/gtksocket.[ch]: Add "child_added", "child_removed" + signals. + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch]: Add + functions gtk_plug_get_id(), gtk_socket_get_id(), + to avoid the user having to worry about realization, + and gdkx.h. + + * tests/testsocket.c: Extend to try out the new signals + and gtk_plug/socket_get_id(). + + * gtk/gtklabel.c (gtk_label_set_pattern_internal): Fix + setting of underline attributes. + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Ignore + DestroyNotify events from SubstructureNotifyMask + + * gdk/x11/gdkwindow-x11.c (gdk_window_reparent): + Switch GDK_WINDOW_TYPE (window) as needed. + + * gdk/x11/gdkwindow-x11.c (gdk_window_new): Clean up, + allow creation of toplevel windows as children of + foreign windows. + + * gtk/gtkplug.c: Remove hacks involving changing private + fields of GdkWindow. + + * gtk/gtkplug.[ch] gtk/gtksocket.c: Work to make + exactly the same signals and notification + be emitted for local embedding as for inter-process + embedding. + 2001-07-04 James Henstridge <james@daa.com.au> * gtk/gtkliststore.h: add missing gtk_list_store_newv prototype. diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index a2c7740b71..5ca9d91952 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -1216,14 +1216,20 @@ gdk_event_translate (GdkEvent *event, GDK_NOTE (EVENTS, g_message ("destroy notify:\twindow: %ld", xevent->xdestroywindow.window)); - - event->any.type = GDK_DESTROY; - event->any.window = window; - - return_val = window_private && !GDK_WINDOW_DESTROYED (window); - - if (window && GDK_WINDOW_XID (window) != GDK_ROOT_WINDOW()) - gdk_window_destroy_notify (window); + + /* Ignore DestroyNotify from SubstructureNotifyMask */ + if (xevent->xdestroywindow.window == xevent->xdestroywindow.event) + { + event->any.type = GDK_DESTROY; + event->any.window = window; + + return_val = window_private && !GDK_WINDOW_DESTROYED (window); + + if (window && GDK_WINDOW_XID (window) != GDK_ROOT_WINDOW()) + gdk_window_destroy_notify (window); + } + else + return_val = FALSE; break; case UnmapNotify: diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 4124769952..9f8aebaa98 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -403,6 +403,26 @@ gdk_window_new (GdkWindow *parent, xattributes_mask |= CWWinGravity; } + /* Sanity checks */ + switch (private->window_type) + { + case GDK_WINDOW_TOPLEVEL: + case GDK_WINDOW_DIALOG: + case GDK_WINDOW_TEMP: + if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT && + GDK_WINDOW_TYPE (parent) != GDK_WINDOW_FOREIGN) + { + g_warning (G_STRLOC "Toplevel windows must be created as children of\n" + "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN"); + xparent = gdk_root_window; + } + case GDK_WINDOW_CHILD: + break; + default: + g_warning (G_STRLOC "cannot make windows of type %d", private->window_type); + return NULL; + } + if (attributes->wclass == GDK_INPUT_OUTPUT) { class = InputOutput; @@ -445,42 +465,16 @@ gdk_window_new (GdkWindow *parent, xattributes.bit_gravity = NorthWestGravity; xattributes_mask |= CWBitGravity; - - switch (private->window_type) + + xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap); + xattributes_mask |= CWColormap; + + if (private->window_type == GDK_WINDOW_TEMP) { - case GDK_WINDOW_TOPLEVEL: - xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap); - xattributes_mask |= CWColormap; - - xparent = gdk_root_window; - break; - - case GDK_WINDOW_CHILD: - xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap); - xattributes_mask |= CWColormap; - break; - - case GDK_WINDOW_DIALOG: - xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap); - xattributes_mask |= CWColormap; - - xparent = gdk_root_window; - break; - - case GDK_WINDOW_TEMP: - xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap); - xattributes_mask |= CWColormap; - - xparent = gdk_root_window; - xattributes.save_under = True; xattributes.override_redirect = True; xattributes.cursor = None; xattributes_mask |= CWSaveUnder | CWOverrideRedirect; - break; - case GDK_WINDOW_ROOT: - g_error ("cannot make windows of type GDK_WINDOW_ROOT"); - break; } } else @@ -1040,6 +1034,7 @@ gdk_window_reparent (GdkWindow *window, g_return_if_fail (window != NULL); 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 (!new_parent) new_parent = gdk_parent_root; @@ -1055,7 +1050,37 @@ gdk_window_reparent (GdkWindow *window, x, y); window_private->parent = (GdkWindowObject *)new_parent; - + + /* Switch the window type as appropriate */ + + switch (GDK_WINDOW_TYPE (new_parent)) + { + case GDK_WINDOW_ROOT: + case GDK_WINDOW_FOREIGN: + /* Now a toplevel */ + if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD) + { + GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL; + XSetWMProtocols (GDK_WINDOW_XDISPLAY (window), + GDK_WINDOW_XID (window), + gdk_wm_window_protocols, 3); + } + case GDK_WINDOW_TOPLEVEL: + case GDK_WINDOW_CHILD: + case GDK_WINDOW_DIALOG: + case GDK_WINDOW_TEMP: + if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && + GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN) + { + /* If we were being sophisticated, we'd save the old window type + * here, and restore it if we were reparented back to the + * toplevel. However, the difference between different types + * of toplevels only really matters on creation anyways. + */ + GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD; + } + } + if (old_parent_private) old_parent_private->children = g_list_remove (old_parent_private->children, window); diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index bff1b76b45..f97ad54d3e 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -197,30 +197,32 @@ static gboolean gtk_drag_highlight_expose (GtkWidget *widget, GdkEventExpose *event, gpointer data); -static void gtk_drag_selection_received (GtkWidget *widget, - GtkSelectionData *selection_data, - guint32 time, - gpointer data); -static void gtk_drag_find_widget (GtkWidget *widget, - GtkDragFindData *data); -static void gtk_drag_proxy_begin (GtkWidget *widget, - GtkDragDestInfo *dest_info, - guint32 time); -static void gtk_drag_dest_realized (GtkWidget *widget); -static void gtk_drag_dest_site_destroy (gpointer data); -static void gtk_drag_dest_leave (GtkWidget *widget, - GdkDragContext *context, - guint time); -static gboolean gtk_drag_dest_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static gboolean gtk_drag_dest_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); +static void gtk_drag_selection_received (GtkWidget *widget, + GtkSelectionData *selection_data, + guint32 time, + gpointer data); +static void gtk_drag_find_widget (GtkWidget *widget, + GtkDragFindData *data); +static void gtk_drag_proxy_begin (GtkWidget *widget, + GtkDragDestInfo *dest_info, + guint32 time); +static void gtk_drag_dest_realized (GtkWidget *widget); +static void gtk_drag_dest_hierarchy_changed (GtkWidget *widget, + GtkWidget *old_toplevel); +static void gtk_drag_dest_site_destroy (gpointer data); +static void gtk_drag_dest_leave (GtkWidget *widget, + GdkDragContext *context, + guint time); +static gboolean gtk_drag_dest_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static gboolean gtk_drag_dest_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); static GtkDragDestInfo * gtk_drag_get_dest_info (GdkDragContext *context, gboolean create); @@ -812,6 +814,8 @@ gtk_drag_dest_set_internal (GtkWidget *widget, gtk_signal_connect (GTK_OBJECT (widget), "realize", GTK_SIGNAL_FUNC (gtk_drag_dest_realized), site); + gtk_signal_connect (GTK_OBJECT (widget), "hierarchy_changed", + GTK_SIGNAL_FUNC (gtk_drag_dest_hierarchy_changed), site); gtk_object_set_data_full (GTK_OBJECT (widget), "gtk-drag-dest", site, gtk_drag_dest_site_destroy); @@ -1428,7 +1432,18 @@ static void gtk_drag_dest_realized (GtkWidget *widget) { GtkWidget *toplevel = gtk_widget_get_toplevel (widget); - gdk_window_register_dnd (toplevel->window); + + if (GTK_WIDGET_TOPLEVEL (toplevel)) + gdk_window_register_dnd (toplevel->window); +} + +static void +gtk_drag_dest_hierarchy_changed (GtkWidget *widget) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (widget); + + if (GTK_WIDGET_TOPLEVEL (toplevel) && GTK_WIDGET_REALIZED (toplevel)) + gdk_window_register_dnd (toplevel->window); } static void diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index 58c910c961..c240144bb2 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -2030,7 +2030,7 @@ gtk_entry_real_activate (GtkEntry *entry) if (entry->activates_default) { toplevel = gtk_widget_get_toplevel (widget); - if (toplevel && GTK_IS_WINDOW (toplevel)) + if (GTK_IS_WINDOW (toplevel)) { window = GTK_WINDOW (toplevel); diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 64f85330ed..db4c7e8ef5 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -492,8 +492,7 @@ gtk_label_setup_mnemonic (GtkLabel *label, return; toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label)); - - if (GTK_IS_WINDOW (toplevel)) + if (GTK_WIDGET_TOPLEVEL (toplevel)) { gtk_window_add_mnemonic (GTK_WINDOW (toplevel), label->mnemonic_keyval, @@ -953,7 +952,10 @@ gtk_label_set_pattern_internal (GtkLabel *label, g_return_if_fail (GTK_IS_LABEL (label)); attrs = gtk_label_pattern_to_attrs (label, pattern); - gtk_label_set_attributes_internal (label, attrs); + + if (label->effective_attrs) + pango_attr_list_unref (label->effective_attrs); + label->effective_attrs = attrs; } void @@ -1092,7 +1094,7 @@ gtk_label_finalize (GObject *object) pango_attr_list_unref (label->attrs); if (label->effective_attrs) - pango_attr_list_unref (label->attrs); + pango_attr_list_unref (label->effective_attrs); g_free (label->select_info); diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c index 2982418928..d17952e953 100644 --- a/gtk/gtkmenubar.c +++ b/gtk/gtkmenubar.c @@ -483,10 +483,10 @@ gtk_menu_bar_hierarchy_changed (GtkWidget *widget, toplevel = gtk_widget_get_toplevel (widget); - if (old_toplevel && GTK_IS_WINDOW (old_toplevel)) + if (old_toplevel) remove_from_window (old_toplevel, menubar); - if (toplevel && GTK_IS_WINDOW (toplevel)) + if (GTK_WIDGET_TOPLEVEL (toplevel)) add_to_window (GTK_WINDOW (toplevel), menubar); } diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c index 03d7e22f06..743a74090d 100644 --- a/gtk/gtkplug.c +++ b/gtk/gtkplug.c @@ -26,6 +26,7 @@ */ #include "gtkmain.h" +#include "gtkmarshal.h" #include "gtkplug.h" #include "gtkprivate.h" @@ -75,6 +76,13 @@ static void xembed_set_info (GdkWindow *window, static GtkWindowClass *parent_class = NULL; static GtkBinClass *bin_class = NULL; +enum { + EMBEDDED, + LAST_SIGNAL +}; + +static guint plug_signals[LAST_SIGNAL] = { 0 }; + GtkType gtk_plug_get_type () { @@ -129,6 +137,15 @@ gtk_plug_class_init (GtkPlugClass *class) #if 0 window_class->accel_entries_changed = gtk_plug_accel_entries_changed; #endif + + plug_signals[EMBEDDED] = + g_signal_new ("embedded", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkPlugClass, embedded), + NULL, NULL, + gtk_marshal_VOID__VOID, + GTK_TYPE_NONE, 0); } static void @@ -146,11 +163,34 @@ static void gtk_plug_set_is_child (GtkPlug *plug, gboolean is_child) { + g_assert (!GTK_WIDGET (plug)->parent); + if (is_child) { + if (plug->modality_window) + handle_modality_off (plug); + + if (plug->modality_group) + { + gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug)); + g_object_unref (plug->modality_group); + plug->modality_group = NULL; + } + GTK_WIDGET_UNSET_FLAGS (plug, GTK_TOPLEVEL); - GTK_PRIVATE_UNSET_FLAG (plug, GTK_ANCHORED); gtk_container_set_resize_mode (GTK_CONTAINER (plug), GTK_RESIZE_PARENT); + + _gtk_widget_propagate_hierarchy_changed (GTK_WIDGET (plug), GTK_WIDGET (plug)); + } + else + { + plug->modality_group = gtk_window_group_new (); + gtk_window_group_add_window (plug->modality_group, GTK_WINDOW (plug)); + + GTK_WIDGET_SET_FLAGS (plug, GTK_TOPLEVEL); + gtk_container_set_resize_mode (GTK_CONTAINER (plug), GTK_RESIZE_QUEUE); + + _gtk_widget_propagate_hierarchy_changed (GTK_WIDGET (plug), NULL); } } @@ -165,12 +205,14 @@ void _gtk_plug_add_to_socket (GtkPlug *plug, GtkSocket *socket) { - GtkWidget *widget = GTK_WIDGET (plug); + GtkWidget *widget; g_return_if_fail (GTK_IS_PLUG (plug)); g_return_if_fail (GTK_IS_SOCKET (socket)); g_return_if_fail (GTK_WIDGET_REALIZED (socket)); + widget = GTK_WIDGET (plug); + gtk_plug_set_is_child (plug, TRUE); plug->same_app = TRUE; socket->plug_widget = widget; @@ -189,6 +231,71 @@ _gtk_plug_add_to_socket (GtkPlug *plug, gtk_widget_queue_resize (widget); } + + g_signal_emit_by_name (G_OBJECT (socket), "plug_added", 0); +} + +/** + * _gtk_plug_add_to_socket: + * @plug: a #GtkPlug + * @socket: a #GtkSocket + * + * Remove a plug from a socket within the same application. + **/ +void +_gtk_plug_remove_from_socket (GtkPlug *plug, + GtkSocket *socket) +{ + GtkWidget *widget; + GdkEvent event; + gboolean result; + gboolean widget_was_visible; + + g_return_if_fail (GTK_IS_PLUG (plug)); + g_return_if_fail (GTK_IS_SOCKET (socket)); + g_return_if_fail (GTK_WIDGET_REALIZED (plug)); + + widget = GTK_WIDGET (plug); + + g_object_ref (plug); + g_object_ref (socket); + + widget_was_visible = GTK_WIDGET_VISIBLE (plug); + + gdk_window_hide (widget->window); + gdk_window_reparent (widget->window, GDK_ROOT_PARENT (), 0, 0); + + GTK_PRIVATE_SET_FLAG (plug, GTK_IN_REPARENT); + gtk_widget_unparent (GTK_WIDGET (plug)); + GTK_PRIVATE_UNSET_FLAG (plug, GTK_IN_REPARENT); + + socket->plug_widget = NULL; + socket->plug_window = NULL; + socket->same_app = FALSE; + + plug->same_app = FALSE; + plug->socket_window = FALSE; + + gtk_plug_set_is_child (plug, FALSE); + + g_signal_emit_by_name (G_OBJECT (socket), "plug_removed", &result); + if (!result) + gtk_widget_destroy (GTK_WIDGET (socket)); + + event.any.type = GDK_DELETE; + event.any.window = g_object_ref (widget->window); + event.any.send_event = FALSE; + + if (!gtk_widget_event (widget, &event)) + gtk_widget_destroy (widget); + + g_object_unref (event.any.window); + g_object_unref (plug); + + if (widget_was_visible && GTK_WIDGET_VISIBLE (socket)) + gtk_widget_queue_resize (GTK_WIDGET (socket)); + + g_object_unref (socket); } void @@ -216,6 +323,9 @@ gtk_plug_construct (GtkPlug *plug, plug->socket_window = NULL; } } + + if (plug->socket_window) + g_signal_emit (G_OBJECT (plug), plug_signals[EMBEDDED], 0); } } @@ -229,6 +339,27 @@ gtk_plug_new (GdkNativeWindow socket_id) return GTK_WIDGET (plug); } +/** + * gtk_plug_get_id: + * @plug: a #GtkPlug. + * + * Gets the window ID of a #GtkPlug widget, which can then + * be used to embed this window inside another window, for + * instance with gtk_sock_add_id (id). + * + * Return value: the window ID for the plug + **/ +GdkNativeWindow +gtk_plug_get_id (GtkPlug *plug) +{ + g_return_val_if_fail (GTK_IS_PLUG (plug), 0); + + if (!GTK_WIDGET_REALIZED (plug)) + gtk_widget_realize (GTK_WIDGET (plug)); + + return GDK_WINDOW_XWINDOW (GTK_WIDGET (plug)->window); +} + static void gtk_plug_unrealize (GtkWidget *widget) { @@ -300,6 +431,8 @@ gtk_plug_realize (GtkWidget *widget) if (GTK_WIDGET_TOPLEVEL (widget)) { + attributes.window_type = GDK_WINDOW_TOPLEVEL; + gdk_error_trap_push (); widget->window = gdk_window_new (plug->socket_window, &attributes, attributes_mask); @@ -312,8 +445,7 @@ gtk_plug_realize (GtkWidget *widget) gdk_error_trap_pop (); widget->window = gdk_window_new (NULL, &attributes, attributes_mask); } - - GDK_WINDOW_TYPE (widget->window) = GDK_WINDOW_TOPLEVEL; + gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget); plug->modality_group = gtk_window_group_new (); @@ -906,7 +1038,104 @@ gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) return GDK_FILTER_REMOVE; } + else if (xevent->xclient.message_type == gdk_atom_intern ("WM_DELETE_WINDOW", FALSE)) + { + /* We filter these out because we take being reparented back to the + * root window as the reliable end of the embedding protocol + */ + + return GDK_FILTER_REMOVE; + } break; + case ReparentNotify: + { + XReparentEvent *xre = &xevent->xreparent; + gboolean was_embedded = plug->socket_window != NULL; + + return_val = GDK_FILTER_REMOVE; + + g_object_ref (plug); + + if (was_embedded) + { + /* End of embedding protocol for previous socket */ + + /* FIXME: race if we remove from another socket and + * then add to a local window before we get notification + * Probably need check in _gtk_plug_add_to_socket + */ + + if (xre->parent != GDK_WINDOW_XWINDOW (plug->socket_window)) + { + GtkWidget *widget = GTK_WIDGET (plug); + + gdk_window_set_user_data (plug->socket_window, NULL); + gdk_window_unref (plug->socket_window); + plug->socket_window = NULL; + + /* Emit a delete window, as if the user attempted + * to close the toplevel. Simple as to how we + * handle WM_DELETE_WINDOW, if it isn't handled + * we destroy the widget. BUt only do this if + * we are being reparented to the root window. + * Moving from one embedder to another should + * be invisible to the app. + */ + + if (xre->parent == GDK_ROOT_WINDOW()) + { + GdkEvent event; + + event.any.type = GDK_DELETE; + event.any.window = g_object_ref (widget->window); + event.any.send_event = FALSE; + + if (!gtk_widget_event (widget, &event)) + gtk_widget_destroy (widget); + + g_object_unref (event.any.window); + } + } + else + break; + } + + if (xre->parent != GDK_ROOT_WINDOW ()) + { + /* Start of embedding protocol */ + + plug->socket_window = gdk_window_lookup (xre->parent); + if (plug->socket_window) + { + gpointer user_data = NULL; + gdk_window_get_user_data (plug->socket_window, &user_data); + + if (user_data) + { + g_warning (G_STRLOC "Plug reparented unexpectedly into window in the same process"); + plug->socket_window = NULL; + break; + } + + g_object_ref (plug->socket_window); + } + else + { + plug->socket_window = gdk_window_foreign_new (xre->parent); + if (!plug->socket_window) /* Already gone */ + break; + } + + /* FIXME: Add grabbed keys here */ + + if (!was_embedded) + g_signal_emit (G_OBJECT (plug), plug_signals[EMBEDDED], 0); + } + + g_object_unref (plug); + + break; + } } return GDK_FILTER_CONTINUE; diff --git a/gtk/gtkplug.h b/gtk/gtkplug.h index d3274c50b4..4c568e817d 100644 --- a/gtk/gtkplug.h +++ b/gtk/gtkplug.h @@ -62,16 +62,21 @@ struct _GtkPlug struct _GtkPlugClass { GtkWindowClass parent_class; + + void (*embedded) (GtkPlug *plug); }; GtkType gtk_plug_get_type (void) G_GNUC_CONST; void gtk_plug_construct (GtkPlug *plug, GdkNativeWindow socket_id); -GtkWidget* gtk_plug_new (GdkNativeWindow socket_id); +GtkWidget* gtk_plug_new (GdkNativeWindow socket_id); +GdkNativeWindow gtk_plug_get_id (GtkPlug *plug); -void _gtk_plug_add_to_socket (GtkPlug *plug, - GtkSocket *socket); +void _gtk_plug_add_to_socket (GtkPlug *plug, + GtkSocket *socket); +void _gtk_plug_remove_from_socket (GtkPlug *plug, + GtkSocket *socket); #ifdef __cplusplus } diff --git a/gtk/gtksocket.c b/gtk/gtksocket.c index a8e76850b1..70e2fb7d37 100644 --- a/gtk/gtksocket.c +++ b/gtk/gtksocket.c @@ -27,8 +27,10 @@ #include "gdk/gdkkeysyms.h" #include "gtkmain.h" +#include "gtkmarshal.h" #include "gtkwindow.h" #include "gtkplug.h" +#include "gtkprivate.h" #include "gtksignal.h" #include "gtksocket.h" #include "gtkdnd.h" @@ -91,6 +93,14 @@ static gboolean xembed_get_info (GdkWindow *gdk_window, /* Local data */ +enum { + PLUG_ADDED, + PLUG_REMOVED, + LAST_SIGNAL +}; + +static guint socket_signals[LAST_SIGNAL] = { 0 }; + static GtkWidgetClass *parent_class = NULL; GtkType @@ -143,6 +153,23 @@ gtk_socket_class_init (GtkSocketClass *class) container_class->remove = gtk_socket_remove; container_class->forall = gtk_socket_forall; + + socket_signals[PLUG_ADDED] = + g_signal_new ("plug_added", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkSocketClass, plug_added), + NULL, NULL, + gtk_marshal_VOID__VOID, + GTK_TYPE_NONE, 0); + socket_signals[PLUG_REMOVED] = + g_signal_new ("plug_removed", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkSocketClass, plug_removed), + _gtk_boolean_handled_accumulator, NULL, + gtk_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); } static void @@ -160,6 +187,14 @@ gtk_socket_init (GtkSocket *socket) socket->need_map = FALSE; } +/** + * gtk_socket_new: + * @void: + * + * Create a new empty #GtkSocket. + * + * Return value: the new #GtkSocket. + **/ GtkWidget* gtk_socket_new (void) { @@ -170,12 +205,85 @@ gtk_socket_new (void) return GTK_WIDGET (socket); } +/** + * gtk_socket_steal: + * @socket: a #GtkSocket + * @id: the XID of an existing toplevel window. + * + * Reparents a pre-existing toplevel window into a #GtkSocket. This is + * meant to embed clients that do not know about embedding into a + * #GtkSocket, however doing so is inherently unreliable, and using + * this function is not recommended. + * + * The #GtkSocket must have already be added into a toplevel window + * before you can make this call. + **/ void gtk_socket_steal (GtkSocket *socket, GdkNativeWindow id) { + g_return_if_fail (GTK_IS_SOCKET (socket)); + g_return_if_fail (GTK_WIDGET_ANCHORED (socket)); + + if (!GTK_WIDGET_REALIZED (socket)) + gtk_widget_realize (GTK_WIDGET (socket)); + gtk_socket_add_window (socket, id, TRUE); } +/** + * gtk_socket_add_id: + * @socket: a #GtkSocket + * @id: the XID of a client participating in the XEMBED protocol. + * + * Adds an XEMBED client, such as a #GtkPlug, to the #GtkSocket. The + * client may be in the same process or in a different process. + * + * To embed a #GtkPlug in a #GtkSocket, you can either create the + * #GtkPlug with gtk_plug_new (0), call gtk_plug_get_id() to get the + * window ID of the plug, and then pass that to the + * gtk_socket_add_id(), or you can call gtk_socket_get_id() to get the + * window ID for the socket, and call gtk_plug_new() passing in that + * ID. + * + * The #GtkSocket must have already be added into a toplevel window + * before you can make this call. + **/ +void +gtk_socket_add_id (GtkSocket *socket, GdkNativeWindow id) +{ + g_return_if_fail (GTK_IS_SOCKET (socket)); + g_return_if_fail (GTK_WIDGET_ANCHORED (socket)); + + if (!GTK_WIDGET_REALIZED (socket)) + gtk_widget_realize (GTK_WIDGET (socket)); + + gtk_socket_add_window (socket, id, TRUE); +} + +/** + * gtk_socket_get_id: + * @socket: a #GtkSocket. + * + * Gets the window ID of a #GtkSocket widget, which can then + * be used to create a client embedded inside the socket, for + * instance with gtk_socket_new (id). The #GtkSocket must + * have already be added into a toplevel window before you + * can make this call. + * + * Return value: the window ID for the socket + **/ +GdkNativeWindow +gtk_socket_get_id (GtkSocket *socket) +{ + g_return_val_if_fail (GTK_IS_SOCKET (socket), 0); + g_return_val_if_fail (GTK_WIDGET_ANCHORED (socket), 0); + + if (!GTK_WIDGET_REALIZED (socket)) + gtk_widget_realize (GTK_WIDGET (socket)); + + return GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window); +} + static void gtk_socket_realize (GtkWidget *widget) { @@ -232,20 +340,20 @@ gtk_socket_realize (GtkWidget *widget) static void gtk_socket_unrealize (GtkWidget *widget) { - GtkSocket *socket; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_SOCKET (widget)); - - socket = GTK_SOCKET (widget); + GtkSocket *socket = GTK_SOCKET (widget); - if (socket->plug_window) + if (socket->plug_widget) + { + _gtk_plug_remove_from_socket (GTK_PLUG (socket->plug_widget), socket); + } + else if (socket->plug_window) { GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); if (toplevel && GTK_IS_WINDOW (toplevel)) gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), GDK_WINDOW_XWINDOW (socket->plug_window)); + g_object_unref (socket->plug_window); socket->plug_window = NULL; } @@ -266,13 +374,7 @@ static void gtk_socket_size_request (GtkWidget *widget, GtkRequisition *requisition) { - GtkSocket *socket; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_SOCKET (widget)); - g_return_if_fail (requisition != NULL); - - socket = GTK_SOCKET (widget); + GtkSocket *socket = GTK_SOCKET (widget); if (socket->plug_widget) { @@ -800,20 +902,10 @@ gtk_socket_remove (GtkContainer *container, GtkWidget *child) { GtkSocket *socket = GTK_SOCKET (container); - gboolean widget_was_visible; g_return_if_fail (child == socket->plug_widget); - widget_was_visible = GTK_WIDGET_VISIBLE (child); - - gtk_widget_unparent (child); - socket->plug_widget = NULL; - - /* queue resize regardless of GTK_WIDGET_VISIBLE (container), - * since that's what is needed by toplevels, which derive from GtkBin. - */ - if (widget_was_visible) - gtk_widget_queue_resize (GTK_WIDGET (container)); + _gtk_plug_remove_from_socket (GTK_PLUG (socket->plug_widget), socket); } static void @@ -965,6 +1057,9 @@ gtk_socket_add_window (GtkSocket *socket, gtk_widget_queue_resize (GTK_WIDGET (socket)); } + + if (socket->plug_window) + g_signal_emit (G_OBJECT (socket), socket_signals[PLUG_ADDED], 0); } @@ -1171,26 +1266,20 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) XCreateWindowEvent *xcwe = &xevent->xcreatewindow; if (!socket->plug_window) - gtk_socket_add_window (socket, xcwe->window, FALSE); - - if (socket->plug_window) { - gdk_error_trap_push (); - gdk_window_move_resize(socket->plug_window, - 0, 0, - widget->allocation.width, - widget->allocation.height); - gdk_flush (); - gdk_error_trap_pop (); - - socket->request_width = xcwe->width; - socket->request_height = xcwe->height; - socket->have_size = TRUE; + gtk_socket_add_window (socket, xcwe->window, FALSE); - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - window created with size: %d %d", - socket->request_width, - socket->request_height)); + if (socket->plug_window) + { + socket->request_width = xcwe->width; + socket->request_height = xcwe->height; + socket->have_size = TRUE; + + GTK_NOTE(PLUGSOCKET, + g_message ("GtkSocket - window created with size: %d %d", + socket->request_width, + socket->request_height)); + } } return_val = GDK_FILTER_REMOVE; @@ -1235,10 +1324,14 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) { 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))) { GtkWidget *toplevel; - + gboolean result; + GTK_NOTE(PLUGSOCKET, g_message ("GtkSocket - destroy notify")); @@ -1247,9 +1340,14 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), xdwe->window); gdk_window_destroy_notify (socket->plug_window); - gtk_widget_destroy (widget); - + g_object_unref (socket->plug_window); socket->plug_window = NULL; + + g_object_ref (widget); + g_signal_emit (G_OBJECT (widget), socket_signals[PLUG_REMOVED], 0, &result); + if (!result) + gtk_widget_destroy (widget); + g_object_unref (widget); return_val = GDK_FILTER_REMOVE; } @@ -1339,6 +1437,27 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) return_val = GDK_FILTER_REMOVE; } break; + case ReparentNotify: + { + XReparentEvent *xre = &xevent->xreparent; + + 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", + socket->request_width, + socket->request_height)); + } + + return_val = GDK_FILTER_REMOVE; + } + + break; + } case UnmapNotify: if (socket->plug_window && xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window)) diff --git a/gtk/gtksocket.h b/gtk/gtksocket.h index 18a762bbe9..14ee4165a1 100644 --- a/gtk/gtksocket.h +++ b/gtk/gtksocket.h @@ -70,13 +70,23 @@ struct _GtkSocket struct _GtkSocketClass { GtkContainerClass parent_class; + + gboolean (*plug_added) (GtkSocket *socket); + gboolean (*plug_removed) (GtkSocket *socket); }; GtkWidget* gtk_socket_new (void); GtkType gtk_socket_get_type (void) G_GNUC_CONST; -void gtk_socket_steal (GtkSocket *socket, + +void gtk_socket_add_id (GtkSocket *socket, + GdkNativeWindow id); +GdkNativeWindow gtk_socket_get_id (GtkSocket *socket); + +#ifndef GTK_DISABLE_DEPRECATED +void gtk_socket_steal (GtkSocket *socket, GdkNativeWindow wid); +#endif /* GTK_DISABLE_DEPRECATED */ #ifdef __cplusplus } diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index a25774438e..ef4eb92246 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -682,7 +682,11 @@ gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column) { GTK_WIDGET_UNSET_FLAGS (tree_column->button, GTK_CAN_FOCUS); if (GTK_WIDGET_HAS_FOCUS (tree_column->button)) - gtk_window_set_focus (GTK_WINDOW (gtk_widget_get_toplevel (tree_column->tree_view)), NULL); + { + GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view); + if (GTK_WIDGET_TOPLEVEL (toplevel)) + gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); + } } tree_column->dirty = TRUE; diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 295855b89f..29bf94167c 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -210,8 +210,6 @@ static void gtk_widget_set_style_recurse (GtkWidget *widget, gpointer client_data); static gint gtk_widget_event_internal (GtkWidget *widget, GdkEvent *event); -static void gtk_widget_propagate_hierarchy_changed (GtkWidget *widget, - gpointer client_data); static gboolean gtk_widget_real_mnemonic_activate (GtkWidget *widget, gboolean group_cycling); static void gtk_widget_aux_info_destroy (GtkWidgetAuxInfo *aux_info); @@ -1500,7 +1498,7 @@ gtk_widget_unparent (GtkWidget *widget) { gtk_container_set_focus_child (GTK_CONTAINER (widget->parent), NULL); - if (GTK_IS_WINDOW (toplevel)) + if (GTK_WIDGET_TOPLEVEL (toplevel)) { GtkWidget *child; @@ -1513,7 +1511,7 @@ gtk_widget_unparent (GtkWidget *widget) gtk_window_set_focus (GTK_WINDOW (toplevel), NULL); } } - if (GTK_IS_WINDOW (toplevel)) + if (GTK_WIDGET_TOPLEVEL (toplevel)) { GtkWidget *child; @@ -1611,7 +1609,7 @@ gtk_widget_unparent (GtkWidget *widget) gtk_signal_emit (GTK_OBJECT (widget), widget_signals[PARENT_SET], old_parent); if (toplevel) { - gtk_widget_propagate_hierarchy_changed (widget, toplevel); + _gtk_widget_propagate_hierarchy_changed (widget, toplevel); g_object_unref (toplevel); } @@ -3091,7 +3089,7 @@ gtk_widget_real_grab_focus (GtkWidget *focus_widget) * be set by the next loop. */ toplevel = gtk_widget_get_toplevel (focus_widget); - if (GTK_IS_WINDOW (toplevel)) + if (GTK_WIDGET_TOPLEVEL (toplevel)) { widget = GTK_WINDOW (toplevel)->focus_widget; @@ -3255,7 +3253,7 @@ gtk_widget_set_name (GtkWidget *widget, g_object_notify (G_OBJECT (widget), "name"); } - +s /** * gtk_widget_get_name: * @widget: a #GtkWidget @@ -3471,7 +3469,7 @@ gtk_widget_set_parent (GtkWidget *widget, gtk_signal_emit (GTK_OBJECT (widget), widget_signals[PARENT_SET], NULL); if (GTK_WIDGET_ANCHORED (widget->parent)) - gtk_widget_propagate_hierarchy_changed (widget, NULL); + _gtk_widget_propagate_hierarchy_changed (widget, NULL); g_object_notify (G_OBJECT (widget), "parent"); } @@ -3928,12 +3926,13 @@ gtk_widget_set_style_recurse (GtkWidget *widget, } static void -gtk_widget_propagate_hierarchy_changed (GtkWidget *widget, - gpointer client_data) +gtk_widget_propagate_hierarchy_changed_recurse (GtkWidget *widget, + gpointer client_data) { gboolean new_anchored; - new_anchored = widget->parent && GTK_WIDGET_ANCHORED (widget->parent); + new_anchored = GTK_WIDGET_TOPLEVEL (widget) || + (widget->parent && GTK_WIDGET_ANCHORED (widget->parent)); if (GTK_WIDGET_ANCHORED (widget) != new_anchored) { @@ -3949,13 +3948,35 @@ gtk_widget_propagate_hierarchy_changed (GtkWidget *widget, if (GTK_IS_CONTAINER (widget)) gtk_container_forall (GTK_CONTAINER (widget), - gtk_widget_propagate_hierarchy_changed, - NULL); + gtk_widget_propagate_hierarchy_changed_recurse, + client_data); gtk_widget_unref (widget); } } +/** + * _gtk_widget_propagate_hierarchy_changed: + * @widget: a #GtkWidget + * @previous_toplevel: Previous toplevel + * + * Propagate changes in the anchored state to a widget and all + * children, unsetting or setting the ANCHORED flag, and + * emitting hierarchy_changed. + **/ +void +_gtk_widget_propagate_hierarchy_changed (GtkWidget *widget, + GtkWidget *previous_toplevel) +{ + if (previous_toplevel) + g_object_ref (previous_toplevel); + + gtk_widget_propagate_hierarchy_changed_recurse (widget, previous_toplevel); + + if (previous_toplevel) + g_object_unref (previous_toplevel); +} + void gtk_widget_reset_rc_styles (GtkWidget *widget) { @@ -4556,14 +4577,16 @@ gtk_widget_set_extension_events (GtkWidget *widget, * seem unlikely, it actually happens when a GtkPlug is embedded * inside a GtkSocket within the same application * - * To reliably find for the toplevel GtkWindow, use + * To reliably find the toplevel GtkWindow, use + * gtk_widget_get_toplevel() and check if the TOPLEVEL flags + * is set on the result. * * GtkWidget *toplevel = gtk_widget_get_toplevel (widget); - * if (GTK_IS_WINDOW (toplevel)) + * if (GTK_WIDGET_TOPLEVEL (toplevel)) * { - * /* Perform action on toplevel. + * [ Perform action on toplevel. ] * } - * + * * Return value: the topmost ancestor of @widget, or @widget itself if there's no ancestor **/ GtkWidget* diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index e8f525fe15..03bae9dbbb 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -733,8 +733,10 @@ void gtk_requisition_free (GtkRequisition *requisition); # define gtk_widget_unref gtk_object_unref #endif /* GTK_TRACE_OBJECTS && __GNUC__ */ -GtkWidgetAuxInfo *_gtk_widget_get_aux_info (GtkWidget *widget, - gboolean create); +GtkWidgetAuxInfo *_gtk_widget_get_aux_info (GtkWidget *widget, + gboolean create); +void _gtk_widget_propagate_hierarchy_changed (GtkWidget *widget, + GtkWidget *previous_toplevel); #ifdef __cplusplus } diff --git a/tests/testsocket.c b/tests/testsocket.c index ab71501f1e..55d0afa980 100644 --- a/tests/testsocket.c +++ b/tests/testsocket.c @@ -1,12 +1,5 @@ #include <gtk/gtk.h> -#if defined (GDK_WINDOWING_X11) -#include "x11/gdkx.h" -#elif defined (GDK_WINDOWING_WIN32) -#include "win32/gdkwin32.h" -#define GDK_WINDOW_XWINDOW(w) (guint)GDK_WINDOW_HWND(w) -#endif - #include <string.h> #include <stdlib.h> #include <stdio.h> @@ -14,9 +7,17 @@ int n_children = 0; +GSList *sockets = NULL; + GtkWidget *window; GtkWidget *vbox; -GtkWidget *lastsocket = NULL; + +typedef struct +{ + GtkWidget *box; + GtkWidget *frame; + GtkWidget *socket; +} Socket; extern guint32 create_child_plug (guint32 xid, gboolean local); @@ -44,12 +45,78 @@ static GtkItemFactoryEntry menu_items[] = { "/File/_Quit", "<control>Q", quit_cb, 0 }, }; +static void +socket_destroyed (GtkWidget *widget, + Socket *socket) +{ + sockets = g_slist_remove (sockets, socket); + g_free (socket); +} + +static void +plug_added (GtkWidget *widget, + Socket *socket) +{ + g_print ("Plug added to socket\n"); + + gtk_widget_show (socket->socket); + gtk_widget_hide (socket->frame); +} + +static gboolean +plug_removed (GtkWidget *widget, + Socket *socket) +{ + g_print ("Plug removed from socket\n"); + + gtk_widget_hide (socket->socket); + gtk_widget_show (socket->frame); + + return TRUE; +} + +static Socket * +create_socket (void) +{ + GtkWidget *label; + + Socket *socket = g_new (Socket, 1); + + socket->box = gtk_vbox_new (FALSE, 0); + + socket->socket = gtk_socket_new (); + + gtk_box_pack_start (GTK_BOX (socket->box), socket->socket, TRUE, TRUE, 0); + + socket->frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (socket->frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (socket->box), socket->frame, TRUE, TRUE, 0); + gtk_widget_show (socket->frame); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), "<span color=\"red\">Empty</span>"); + gtk_container_add (GTK_CONTAINER (socket->frame), label); + gtk_widget_show (label); + + sockets = g_slist_prepend (sockets, socket); + + + g_signal_connect (G_OBJECT (socket->socket), "destroy", + G_CALLBACK (socket_destroyed), socket); + g_signal_connect (G_OBJECT (socket->socket), "plug_added", + G_CALLBACK (plug_added), socket); + g_signal_connect (G_OBJECT (socket->socket), "plug_removed", + G_CALLBACK (plug_removed), socket); + + return socket; +} + void steal (GtkWidget *window, GtkEntry *entry) { guint32 xid; const gchar *text; - GtkWidget *socket; + Socket *socket; text = gtk_entry_get_text (entry); @@ -60,9 +127,9 @@ steal (GtkWidget *window, GtkEntry *entry) return; } - socket = gtk_socket_new (); - gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0); - gtk_widget_show (socket); + socket = create_socket (); + gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0); + gtk_widget_show (socket->box); gtk_socket_steal (GTK_SOCKET (socket), xid); } @@ -70,9 +137,11 @@ steal (GtkWidget *window, GtkEntry *entry) void remove_child (GtkWidget *window) { - if (lastsocket) - gtk_widget_destroy (lastsocket); - lastsocket = NULL; + if (sockets) + { + Socket *socket = sockets->data; + gtk_widget_destroy (socket->box); + } } static gboolean @@ -96,11 +165,11 @@ child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data) } else { - GtkWidget *socket = gtk_socket_new (); - gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0); - gtk_widget_show (socket); + Socket *socket = create_socket (); + gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0); + gtk_widget_show (socket->box); - gtk_socket_steal (GTK_SOCKET (socket), xid); + gtk_socket_add_id (GTK_SOCKET (socket->socket), xid); } g_free (line); return TRUE; @@ -125,26 +194,22 @@ void add_child (GtkWidget *window, gboolean active) { - GtkWidget *socket; + Socket *socket; char *argv[3] = { "./testsocket_child", NULL, NULL }; char buffer[20]; int out_fd; GIOChannel *channel; GError *error = NULL; - socket = gtk_socket_new (); - gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0); - gtk_widget_show (socket); - - lastsocket = socket; - if (active) { - sprintf(buffer, "%#lx", GDK_WINDOW_XWINDOW (socket->window)); + socket = create_socket (); + gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0); + gtk_widget_show (socket->box); + sprintf(buffer, "%#lx", gtk_socket_get_id (GTK_SOCKET (socket->socket))); argv[1] = buffer; } -#if 1 if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, &out_fd, NULL, &error)) { fprintf (stderr, "Can't exec testsocket_child: %s\n", error->message); @@ -161,10 +226,6 @@ add_child (GtkWidget *window, } g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, NULL); - -#else - fprintf(stderr,"%s\n", buffer); -#endif } void @@ -182,15 +243,13 @@ add_passive_child (GtkWidget *window) void add_local_child (GtkWidget *window) { - GtkWidget *socket; - - socket = gtk_socket_new (); - gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0); - gtk_widget_show (socket); + Socket *socket; - lastsocket = socket; + socket = create_socket (); + gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0); + gtk_widget_show (socket->box); - create_child_plug (GDK_WINDOW_XWINDOW (socket->window), TRUE); + create_child_plug (gtk_socket_get_id (GTK_SOCKET (socket->socket)), TRUE); } int |