Check GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel (widget)), not

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.
This commit is contained in:
Owen Taylor 2001-07-05 02:58:34 +00:00 committed by Owen Taylor
parent 3da3e77620
commit c1a14d036d
21 changed files with 1076 additions and 185 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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:

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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 ();
@ -904,9 +1036,106 @@ gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
xevent->xclient.data.l[0]);
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;

View File

@ -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
}

View File

@ -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;
GtkSocket *socket = GTK_SOCKET (widget);
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_SOCKET (widget));
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))

View File

@ -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
}

View File

@ -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;

View File

@ -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*

View File

@ -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
}

View File

@ -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 *socket;
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);
lastsocket = socket;
create_child_plug (GDK_WINDOW_XWINDOW (socket->window), TRUE);
create_child_plug (gtk_socket_get_id (GTK_SOCKET (socket->socket)), TRUE);
}
int