summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog56
-rw-r--r--ChangeLog.pre-2-056
-rw-r--r--ChangeLog.pre-2-1056
-rw-r--r--ChangeLog.pre-2-256
-rw-r--r--ChangeLog.pre-2-456
-rw-r--r--ChangeLog.pre-2-656
-rw-r--r--ChangeLog.pre-2-856
-rw-r--r--gdk/x11/gdkevents-x11.c22
-rw-r--r--gdk/x11/gdkwindow-x11.c89
-rw-r--r--gtk/gtkdnd.c65
-rw-r--r--gtk/gtkentry.c2
-rw-r--r--gtk/gtklabel.c10
-rw-r--r--gtk/gtkmenubar.c4
-rw-r--r--gtk/gtkplug.c237
-rw-r--r--gtk/gtkplug.h11
-rw-r--r--gtk/gtksocket.c211
-rw-r--r--gtk/gtksocket.h12
-rw-r--r--gtk/gtktreeviewcolumn.c6
-rw-r--r--gtk/gtkwidget.c57
-rw-r--r--gtk/gtkwidget.h6
-rw-r--r--tests/testsocket.c137
21 files changed, 1076 insertions, 185 deletions
diff --git a/ChangeLog b/ChangeLog
index 565f2a4075..e4928ac7c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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