For XEMBED embedding add a _XEMBED_INFO property to the client with

Mon Jul  2 16:53:25 2001  Owen Taylor  <otaylor@redhat.com>

	* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
	XEMBED embedding add a _XEMBED_INFO property to the
	client with version number and a "mapped" flags.
	Use the mapped flag instead of the racy MapRequestEvent

        * gtk/gtksocket.c: Clean up the gtk_socket_steal()
	code to reliably set things (when the child is a passive
	embedder participating in the XEMBED protocol) intead
	of just being a hack for embedding non-participating
	programs. Fix various bugs and race conditions.

	* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
	work by simply making the GtkSocket the gtk parent
	of the GtkPlug. Set a flag in this case and make
	the GtkPlug work like a normal container by overriding
	methods such as check_resize and "chaining past" GtkWindow
	to GtkBin.

 	* gtk/gtkentry.c (gtk_entry_real_activate)
	  gtk/gtkmain.c (gtk_propagate_event):
 	Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).

	* gtk/gtkwidget.c (gtk_widget_get_toplevel,
	gtk_widget_get_ancestor):
	Explain	why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
	might not give the expected result and recommend
	an alternative.

	* tests/testsocket.c tests/testsocket_child.c
	tests/testsocket_common.c tests/Makefile.am: Extended
	to test different type of adding plugs to sockets
	(local,active,passive),	and to test mapping/unmapping
	the plug.

 	* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
 	mark the window as destroyed until after we
 	called _gdk_windowing_window_destroy().
	(_gdk_windowing_window_destroy() may use GDK functions
	on the window.)

 	* gdk/x11/gdkinput.c: Remove the check for finalization -
 	devices can be finalized under some circumnstances.

 	* gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
 	small problem with GDK_TYPE_DEVICE.
This commit is contained in:
Owen Taylor 2001-07-03 14:14:30 +00:00 committed by Owen Taylor
parent b6cc525fa0
commit f409cd9b7f
21 changed files with 1145 additions and 292 deletions

View File

@ -1,3 +1,51 @@
Mon Jul 2 16:53:25 2001 Owen Taylor <otaylor@redhat.com>
* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
XEMBED embedding add a _XEMBED_INFO property to the
client with version number and a "mapped" flags.
Use the mapped flag instead of the racy MapRequestEvent
* gtk/gtksocket.c: Clean up the gtk_socket_steal()
code to reliably set things (when the child is a passive
embedder participating in the XEMBED protocol) intead
of just being a hack for embedding non-participating
programs. Fix various bugs and race conditions.
* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
work by simply making the GtkSocket the gtk parent
of the GtkPlug. Set a flag in this case and make
the GtkPlug work like a normal container by overriding
methods such as check_resize and "chaining past" GtkWindow
to GtkBin.
* gtk/gtkentry.c (gtk_entry_real_activate)
gtk/gtkmain.c (gtk_propagate_event):
Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
* gtk/gtkwidget.c (gtk_widget_get_toplevel,
gtk_widget_get_ancestor):
Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
might not give the expected result and recommend
an alternative.
* tests/testsocket.c tests/testsocket_child.c
tests/testsocket_common.c tests/Makefile.am: Extended
to test different type of adding plugs to sockets
(local,active,passive), and to test mapping/unmapping
the plug.
* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
mark the window as destroyed until after we
called _gdk_windowing_window_destroy().
(_gdk_windowing_window_destroy() may use GDK functions
on the window.)
* gdk/x11/gdkinput.c: Remove the check for finalization -
devices can be finalized under some circumnstances.
* gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
small problem with GDK_TYPE_DEVICE.
2001-07-02 Havoc Pennington <hp@pobox.com> 2001-07-02 Havoc Pennington <hp@pobox.com>
* gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to

View File

@ -1,3 +1,51 @@
Mon Jul 2 16:53:25 2001 Owen Taylor <otaylor@redhat.com>
* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
XEMBED embedding add a _XEMBED_INFO property to the
client with version number and a "mapped" flags.
Use the mapped flag instead of the racy MapRequestEvent
* gtk/gtksocket.c: Clean up the gtk_socket_steal()
code to reliably set things (when the child is a passive
embedder participating in the XEMBED protocol) intead
of just being a hack for embedding non-participating
programs. Fix various bugs and race conditions.
* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
work by simply making the GtkSocket the gtk parent
of the GtkPlug. Set a flag in this case and make
the GtkPlug work like a normal container by overriding
methods such as check_resize and "chaining past" GtkWindow
to GtkBin.
* gtk/gtkentry.c (gtk_entry_real_activate)
gtk/gtkmain.c (gtk_propagate_event):
Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
* gtk/gtkwidget.c (gtk_widget_get_toplevel,
gtk_widget_get_ancestor):
Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
might not give the expected result and recommend
an alternative.
* tests/testsocket.c tests/testsocket_child.c
tests/testsocket_common.c tests/Makefile.am: Extended
to test different type of adding plugs to sockets
(local,active,passive), and to test mapping/unmapping
the plug.
* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
mark the window as destroyed until after we
called _gdk_windowing_window_destroy().
(_gdk_windowing_window_destroy() may use GDK functions
on the window.)
* gdk/x11/gdkinput.c: Remove the check for finalization -
devices can be finalized under some circumnstances.
* gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
small problem with GDK_TYPE_DEVICE.
2001-07-02 Havoc Pennington <hp@pobox.com> 2001-07-02 Havoc Pennington <hp@pobox.com>
* gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to

View File

@ -1,3 +1,51 @@
Mon Jul 2 16:53:25 2001 Owen Taylor <otaylor@redhat.com>
* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
XEMBED embedding add a _XEMBED_INFO property to the
client with version number and a "mapped" flags.
Use the mapped flag instead of the racy MapRequestEvent
* gtk/gtksocket.c: Clean up the gtk_socket_steal()
code to reliably set things (when the child is a passive
embedder participating in the XEMBED protocol) intead
of just being a hack for embedding non-participating
programs. Fix various bugs and race conditions.
* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
work by simply making the GtkSocket the gtk parent
of the GtkPlug. Set a flag in this case and make
the GtkPlug work like a normal container by overriding
methods such as check_resize and "chaining past" GtkWindow
to GtkBin.
* gtk/gtkentry.c (gtk_entry_real_activate)
gtk/gtkmain.c (gtk_propagate_event):
Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
* gtk/gtkwidget.c (gtk_widget_get_toplevel,
gtk_widget_get_ancestor):
Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
might not give the expected result and recommend
an alternative.
* tests/testsocket.c tests/testsocket_child.c
tests/testsocket_common.c tests/Makefile.am: Extended
to test different type of adding plugs to sockets
(local,active,passive), and to test mapping/unmapping
the plug.
* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
mark the window as destroyed until after we
called _gdk_windowing_window_destroy().
(_gdk_windowing_window_destroy() may use GDK functions
on the window.)
* gdk/x11/gdkinput.c: Remove the check for finalization -
devices can be finalized under some circumnstances.
* gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
small problem with GDK_TYPE_DEVICE.
2001-07-02 Havoc Pennington <hp@pobox.com> 2001-07-02 Havoc Pennington <hp@pobox.com>
* gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to

View File

@ -1,3 +1,51 @@
Mon Jul 2 16:53:25 2001 Owen Taylor <otaylor@redhat.com>
* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
XEMBED embedding add a _XEMBED_INFO property to the
client with version number and a "mapped" flags.
Use the mapped flag instead of the racy MapRequestEvent
* gtk/gtksocket.c: Clean up the gtk_socket_steal()
code to reliably set things (when the child is a passive
embedder participating in the XEMBED protocol) intead
of just being a hack for embedding non-participating
programs. Fix various bugs and race conditions.
* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
work by simply making the GtkSocket the gtk parent
of the GtkPlug. Set a flag in this case and make
the GtkPlug work like a normal container by overriding
methods such as check_resize and "chaining past" GtkWindow
to GtkBin.
* gtk/gtkentry.c (gtk_entry_real_activate)
gtk/gtkmain.c (gtk_propagate_event):
Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
* gtk/gtkwidget.c (gtk_widget_get_toplevel,
gtk_widget_get_ancestor):
Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
might not give the expected result and recommend
an alternative.
* tests/testsocket.c tests/testsocket_child.c
tests/testsocket_common.c tests/Makefile.am: Extended
to test different type of adding plugs to sockets
(local,active,passive), and to test mapping/unmapping
the plug.
* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
mark the window as destroyed until after we
called _gdk_windowing_window_destroy().
(_gdk_windowing_window_destroy() may use GDK functions
on the window.)
* gdk/x11/gdkinput.c: Remove the check for finalization -
devices can be finalized under some circumnstances.
* gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
small problem with GDK_TYPE_DEVICE.
2001-07-02 Havoc Pennington <hp@pobox.com> 2001-07-02 Havoc Pennington <hp@pobox.com>
* gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to

View File

@ -1,3 +1,51 @@
Mon Jul 2 16:53:25 2001 Owen Taylor <otaylor@redhat.com>
* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
XEMBED embedding add a _XEMBED_INFO property to the
client with version number and a "mapped" flags.
Use the mapped flag instead of the racy MapRequestEvent
* gtk/gtksocket.c: Clean up the gtk_socket_steal()
code to reliably set things (when the child is a passive
embedder participating in the XEMBED protocol) intead
of just being a hack for embedding non-participating
programs. Fix various bugs and race conditions.
* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
work by simply making the GtkSocket the gtk parent
of the GtkPlug. Set a flag in this case and make
the GtkPlug work like a normal container by overriding
methods such as check_resize and "chaining past" GtkWindow
to GtkBin.
* gtk/gtkentry.c (gtk_entry_real_activate)
gtk/gtkmain.c (gtk_propagate_event):
Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
* gtk/gtkwidget.c (gtk_widget_get_toplevel,
gtk_widget_get_ancestor):
Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
might not give the expected result and recommend
an alternative.
* tests/testsocket.c tests/testsocket_child.c
tests/testsocket_common.c tests/Makefile.am: Extended
to test different type of adding plugs to sockets
(local,active,passive), and to test mapping/unmapping
the plug.
* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
mark the window as destroyed until after we
called _gdk_windowing_window_destroy().
(_gdk_windowing_window_destroy() may use GDK functions
on the window.)
* gdk/x11/gdkinput.c: Remove the check for finalization -
devices can be finalized under some circumnstances.
* gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
small problem with GDK_TYPE_DEVICE.
2001-07-02 Havoc Pennington <hp@pobox.com> 2001-07-02 Havoc Pennington <hp@pobox.com>
* gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to

View File

@ -1,3 +1,51 @@
Mon Jul 2 16:53:25 2001 Owen Taylor <otaylor@redhat.com>
* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
XEMBED embedding add a _XEMBED_INFO property to the
client with version number and a "mapped" flags.
Use the mapped flag instead of the racy MapRequestEvent
* gtk/gtksocket.c: Clean up the gtk_socket_steal()
code to reliably set things (when the child is a passive
embedder participating in the XEMBED protocol) intead
of just being a hack for embedding non-participating
programs. Fix various bugs and race conditions.
* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
work by simply making the GtkSocket the gtk parent
of the GtkPlug. Set a flag in this case and make
the GtkPlug work like a normal container by overriding
methods such as check_resize and "chaining past" GtkWindow
to GtkBin.
* gtk/gtkentry.c (gtk_entry_real_activate)
gtk/gtkmain.c (gtk_propagate_event):
Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
* gtk/gtkwidget.c (gtk_widget_get_toplevel,
gtk_widget_get_ancestor):
Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
might not give the expected result and recommend
an alternative.
* tests/testsocket.c tests/testsocket_child.c
tests/testsocket_common.c tests/Makefile.am: Extended
to test different type of adding plugs to sockets
(local,active,passive), and to test mapping/unmapping
the plug.
* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
mark the window as destroyed until after we
called _gdk_windowing_window_destroy().
(_gdk_windowing_window_destroy() may use GDK functions
on the window.)
* gdk/x11/gdkinput.c: Remove the check for finalization -
devices can be finalized under some circumnstances.
* gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
small problem with GDK_TYPE_DEVICE.
2001-07-02 Havoc Pennington <hp@pobox.com> 2001-07-02 Havoc Pennington <hp@pobox.com>
* gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to

View File

@ -1,3 +1,51 @@
Mon Jul 2 16:53:25 2001 Owen Taylor <otaylor@redhat.com>
* gtk/xembed.h gtk/gtkplug.c gtk/gtksocket.c: For
XEMBED embedding add a _XEMBED_INFO property to the
client with version number and a "mapped" flags.
Use the mapped flag instead of the racy MapRequestEvent
* gtk/gtksocket.c: Clean up the gtk_socket_steal()
code to reliably set things (when the child is a passive
embedder participating in the XEMBED protocol) intead
of just being a hack for embedding non-participating
programs. Fix various bugs and race conditions.
* gtk/gtksocket.[ch] gtk/gtkplug.[ch]: Make local embedding
work by simply making the GtkSocket the gtk parent
of the GtkPlug. Set a flag in this case and make
the GtkPlug work like a normal container by overriding
methods such as check_resize and "chaining past" GtkWindow
to GtkBin.
* gtk/gtkentry.c (gtk_entry_real_activate)
gtk/gtkmain.c (gtk_propagate_event):
Eliminate use of gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW).
* gtk/gtkwidget.c (gtk_widget_get_toplevel,
gtk_widget_get_ancestor):
Explain why gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)
might not give the expected result and recommend
an alternative.
* tests/testsocket.c tests/testsocket_child.c
tests/testsocket_common.c tests/Makefile.am: Extended
to test different type of adding plugs to sockets
(local,active,passive), and to test mapping/unmapping
the plug.
* gdk/gdkwindow.c (_gdk_window_destroy_hierarchy): Don't
mark the window as destroyed until after we
called _gdk_windowing_window_destroy().
(_gdk_windowing_window_destroy() may use GDK functions
on the window.)
* gdk/x11/gdkinput.c: Remove the check for finalization -
devices can be finalized under some circumnstances.
* gdk/x11/gdkinput-x11.c (gdk_input_device_new): Fix
small problem with GDK_TYPE_DEVICE.
2001-07-02 Havoc Pennington <hp@pobox.com> 2001-07-02 Havoc Pennington <hp@pobox.com>
* gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to * gdk/x11/gdkwindow-x11.c (gdk_wmspec_change_state): fix to

View File

@ -293,7 +293,6 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
if (!GDK_WINDOW_DESTROYED (window)) if (!GDK_WINDOW_DESTROYED (window))
{ {
private->state |= GDK_WINDOW_STATE_WITHDRAWN; private->state |= GDK_WINDOW_STATE_WITHDRAWN;
private->destroyed = TRUE;
if (private->parent) if (private->parent)
{ {
@ -332,6 +331,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
} }
_gdk_windowing_window_destroy (window, recursing, foreign_destroy); _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
private->destroyed = TRUE;
if (private->filters) if (private->filters)
{ {

View File

@ -96,7 +96,7 @@ gdk_input_device_new (XDeviceInfo *device, gint include_core)
XAnyClassPtr class; XAnyClassPtr class;
gint i,j; gint i,j;
gdkdev = g_object_new (GDK_TYPE_DEVICE_PRIVATE, 1); gdkdev = g_object_new (GDK_TYPE_DEVICE, NULL);
gdkdev->deviceid = device->id; gdkdev->deviceid = device->id;
if (device->name[0]) if (device->name[0])

View File

@ -66,18 +66,6 @@ _gdk_init_input_core (void)
gdk_core_pointer->keys = NULL; gdk_core_pointer->keys = NULL;
} }
static void
gdk_device_finalize (GObject *object)
{
g_error ("A GdkDevice object was finalized. This should not happen");
}
static void
gdk_device_class_init (GObjectClass *class)
{
class->finalize = gdk_device_finalize;
}
GType GType
gdk_device_get_type (void) gdk_device_get_type (void)
{ {
@ -90,7 +78,7 @@ gdk_device_get_type (void)
sizeof (GdkDeviceClass), sizeof (GdkDeviceClass),
(GBaseInitFunc) NULL, (GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL, (GBaseFinalizeFunc) NULL,
(GClassInitFunc) gdk_device_class_init, (GClassInitFunc) NULL,
NULL, /* class_finalize */ NULL, /* class_finalize */
NULL, /* class_data */ NULL, /* class_data */
sizeof (GdkDevicePrivate), sizeof (GdkDevicePrivate),

View File

@ -2022,19 +2022,23 @@ static void
gtk_entry_real_activate (GtkEntry *entry) gtk_entry_real_activate (GtkEntry *entry)
{ {
GtkWindow *window; GtkWindow *window;
GtkWidget *toplevel;
GtkWidget *widget; GtkWidget *widget;
widget = GTK_WIDGET (entry); widget = GTK_WIDGET (entry);
if (entry->activates_default) if (entry->activates_default)
{ {
window = (GtkWindow *) gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); toplevel = gtk_widget_get_toplevel (widget);
if (toplevel && GTK_IS_WINDOW (toplevel))
{
window = GTK_WINDOW (toplevel);
if (window && if (window && window->default_widget != widget)
window->default_widget != widget)
gtk_window_activate_default (window); gtk_window_activate_default (window);
} }
} }
}
static void static void
gtk_entry_keymap_direction_changed (GdkKeymap *keymap, gtk_entry_keymap_direction_changed (GdkKeymap *keymap,

View File

@ -1627,9 +1627,8 @@ gtk_propagate_event (GtkWidget *widget,
*/ */
GtkWidget *window; GtkWidget *window;
window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); window = gtk_widget_get_toplevel (widget);
if (window && GTK_IS_WINDOW (window))
if (window)
{ {
/* If there is a grab within the window, give the grab widget /* If there is a grab within the window, give the grab widget
* a first crack at the key event * a first crack at the key event
@ -1639,8 +1638,8 @@ gtk_propagate_event (GtkWidget *widget,
if (!handled_event) if (!handled_event)
{ {
window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); window = gtk_widget_get_toplevel (widget);
if (window) if (window && GTK_IS_WINDOW (window))
{ {
if (GTK_WIDGET_IS_SENSITIVE (window)) if (GTK_WIDGET_IS_SENSITIVE (window))
gtk_widget_event (window, event); gtk_widget_event (window, event);

View File

@ -27,6 +27,7 @@
#include "gtkmain.h" #include "gtkmain.h"
#include "gtkplug.h" #include "gtkplug.h"
#include "gtkprivate.h"
#include "gdk/gdkkeysyms.h" #include "gdk/gdkkeysyms.h"
#include "x11/gdkx.h" #include "x11/gdkx.h"
@ -37,6 +38,12 @@ static void gtk_plug_class_init (GtkPlugClass *klass);
static void gtk_plug_init (GtkPlug *plug); static void gtk_plug_init (GtkPlug *plug);
static void gtk_plug_realize (GtkWidget *widget); static void gtk_plug_realize (GtkWidget *widget);
static void gtk_plug_unrealize (GtkWidget *widget); static void gtk_plug_unrealize (GtkWidget *widget);
static void gtk_plug_show (GtkWidget *widget);
static void gtk_plug_hide (GtkWidget *widget);
static void gtk_plug_map (GtkWidget *widget);
static void gtk_plug_unmap (GtkWidget *widget);
static void gtk_plug_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static gboolean gtk_plug_key_press_event (GtkWidget *widget, static gboolean gtk_plug_key_press_event (GtkWidget *widget,
GdkEventKey *event); GdkEventKey *event);
static void gtk_plug_forward_key_press (GtkPlug *plug, static void gtk_plug_forward_key_press (GtkPlug *plug,
@ -45,6 +52,7 @@ static void gtk_plug_set_focus (GtkWindow *window,
GtkWidget *focus); GtkWidget *focus);
static gboolean gtk_plug_focus (GtkWidget *widget, static gboolean gtk_plug_focus (GtkWidget *widget,
GtkDirectionType direction); GtkDirectionType direction);
static void gtk_plug_check_resize (GtkContainer *container);
static void gtk_plug_accel_entries_changed (GtkWindow *window); static void gtk_plug_accel_entries_changed (GtkWindow *window);
static GdkFilterReturn gtk_plug_filter_func (GdkXEvent *gdk_xevent, static GdkFilterReturn gtk_plug_filter_func (GdkXEvent *gdk_xevent,
GdkEvent *event, GdkEvent *event,
@ -58,11 +66,14 @@ static void send_xembed_message (GtkPlug *plug,
glong data1, glong data1,
glong data2, glong data2,
guint32 time); guint32 time);
static void xembed_set_info (GdkWindow *window,
unsigned long flags);
/* From Tk */ /* From Tk */
#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
static GtkWindowClass *parent_class = NULL; static GtkWindowClass *parent_class = NULL;
static GtkBinClass *bin_class = NULL;
GtkType GtkType
gtk_plug_get_type () gtk_plug_get_type ()
@ -95,15 +106,25 @@ gtk_plug_class_init (GtkPlugClass *class)
{ {
GtkWidgetClass *widget_class = (GtkWidgetClass *)class; GtkWidgetClass *widget_class = (GtkWidgetClass *)class;
GtkWindowClass *window_class = (GtkWindowClass *)class; GtkWindowClass *window_class = (GtkWindowClass *)class;
GtkContainerClass *container_class = (GtkContainerClass *)class;
parent_class = gtk_type_class (GTK_TYPE_WINDOW); parent_class = gtk_type_class (GTK_TYPE_WINDOW);
bin_class = gtk_type_class (GTK_TYPE_BIN);
widget_class->realize = gtk_plug_realize; widget_class->realize = gtk_plug_realize;
widget_class->unrealize = gtk_plug_unrealize; widget_class->unrealize = gtk_plug_unrealize;
widget_class->key_press_event = gtk_plug_key_press_event; widget_class->key_press_event = gtk_plug_key_press_event;
widget_class->show = gtk_plug_show;
widget_class->hide = gtk_plug_hide;
widget_class->map = gtk_plug_map;
widget_class->unmap = gtk_plug_unmap;
widget_class->size_allocate = gtk_plug_size_allocate;
widget_class->focus = gtk_plug_focus; widget_class->focus = gtk_plug_focus;
container_class->check_resize = gtk_plug_check_resize;
window_class->set_focus = gtk_plug_set_focus; window_class->set_focus = gtk_plug_set_focus;
#if 0 #if 0
window_class->accel_entries_changed = gtk_plug_accel_entries_changed; window_class->accel_entries_changed = gtk_plug_accel_entries_changed;
@ -121,18 +142,79 @@ gtk_plug_init (GtkPlug *plug)
window->auto_shrink = TRUE; window->auto_shrink = TRUE;
} }
static void
gtk_plug_set_is_child (GtkPlug *plug,
gboolean is_child)
{
if (is_child)
{
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_plug_add_to_socket:
* @plug: a #GtkPlug
* @socket: a #GtkSocket
*
* Add a plug to a socket within the same application.
**/
void void
gtk_plug_construct (GtkPlug *plug, GdkNativeWindow socket_id) _gtk_plug_add_to_socket (GtkPlug *plug,
GtkSocket *socket)
{
GtkWidget *widget = GTK_WIDGET (plug);
g_return_if_fail (GTK_IS_PLUG (plug));
g_return_if_fail (GTK_IS_SOCKET (socket));
g_return_if_fail (GTK_WIDGET_REALIZED (socket));
gtk_plug_set_is_child (plug, TRUE);
plug->same_app = TRUE;
socket->plug_widget = widget;
gtk_widget_set_parent (widget, GTK_WIDGET (socket));
if (GTK_WIDGET_REALIZED (widget))
gdk_window_reparent (widget->window, plug->socket_window, 0, 0);
else
gtk_widget_realize (widget);
if (GTK_WIDGET_VISIBLE (socket) && GTK_WIDGET_VISIBLE (widget))
{
if (GTK_WIDGET_MAPPED (socket))
gtk_widget_map (widget);
gtk_widget_queue_resize (widget);
}
}
void
gtk_plug_construct (GtkPlug *plug,
GdkNativeWindow socket_id)
{ {
if (socket_id) if (socket_id)
{ {
plug->socket_window = gdk_window_lookup (socket_id); gpointer user_data = NULL;
plug->same_app = TRUE;
if (plug->socket_window == NULL) plug->socket_window = gdk_window_lookup (socket_id);
{
if (plug->socket_window)
gdk_window_get_user_data (plug->socket_window, &user_data);
else
plug->socket_window = gdk_window_foreign_new (socket_id); plug->socket_window = gdk_window_foreign_new (socket_id);
plug->same_app = FALSE;
if (user_data)
{
if (GTK_IS_SOCKET (user_data))
_gtk_plug_add_to_socket (plug, user_data);
else
{
g_warning (G_STRLOC "Can't create GtkPlug as child of non-GtkSocket");
plug->socket_window = NULL;
}
} }
} }
} }
@ -164,11 +246,14 @@ gtk_plug_unrealize (GtkWidget *widget)
plug->socket_window = NULL; plug->socket_window = NULL;
} }
if (!plug->same_app)
{
if (plug->modality_window) if (plug->modality_window)
handle_modality_off (plug); handle_modality_off (plug);
gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug)); gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug));
g_object_unref (plug->modality_group); g_object_unref (plug->modality_group);
}
if (GTK_WIDGET_CLASS (parent_class)->unrealize) if (GTK_WIDGET_CLASS (parent_class)->unrealize)
(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
@ -213,6 +298,8 @@ gtk_plug_realize (GtkWidget *widget)
attributes_mask |= (window->title ? GDK_WA_TITLE : 0); attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0); attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
if (GTK_WIDGET_TOPLEVEL (widget))
{
gdk_error_trap_push (); gdk_error_trap_push ();
widget->window = gdk_window_new (plug->socket_window, widget->window = gdk_window_new (plug->socket_window,
&attributes, attributes_mask); &attributes, attributes_mask);
@ -227,15 +314,116 @@ gtk_plug_realize (GtkWidget *widget)
} }
GDK_WINDOW_TYPE (widget->window) = GDK_WINDOW_TOPLEVEL; GDK_WINDOW_TYPE (widget->window) = GDK_WINDOW_TOPLEVEL;
gdk_window_set_user_data (widget->window, window);
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget); gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget);
plug->modality_group = gtk_window_group_new (); plug->modality_group = gtk_window_group_new ();
gtk_window_group_add_window (plug->modality_group, window); gtk_window_group_add_window (plug->modality_group, window);
xembed_set_info (widget->window, 0);
}
else
widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
gdk_window_set_user_data (widget->window, window);
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
}
static void
gtk_plug_show (GtkWidget *widget)
{
if (GTK_WIDGET_TOPLEVEL (widget))
GTK_WIDGET_CLASS (parent_class)->show (widget);
else
GTK_WIDGET_CLASS (bin_class)->show (widget);
}
static void
gtk_plug_hide (GtkWidget *widget)
{
if (GTK_WIDGET_TOPLEVEL (widget))
GTK_WIDGET_CLASS (parent_class)->hide (widget);
else
GTK_WIDGET_CLASS (bin_class)->hide (widget);
}
/* From gdkinternals.h */
void gdk_synthesize_window_state (GdkWindow *window,
GdkWindowState unset_flags,
GdkWindowState set_flags);
static void
gtk_plug_map (GtkWidget *widget)
{
if (GTK_WIDGET_TOPLEVEL (widget))
{
GtkBin *bin = GTK_BIN (widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
if (bin->child &&
GTK_WIDGET_VISIBLE (bin->child) &&
!GTK_WIDGET_MAPPED (bin->child))
gtk_widget_map (bin->child);
xembed_set_info (widget->window, XEMBED_MAPPED);
gdk_synthesize_window_state (widget->window,
GDK_WINDOW_STATE_WITHDRAWN,
0);
}
else
GTK_WIDGET_CLASS (bin_class)->map (widget);
}
static void
gtk_plug_unmap (GtkWidget *widget)
{
if (GTK_WIDGET_TOPLEVEL (widget))
{
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
gdk_window_hide (widget->window);
xembed_set_info (widget->window, 0);
gdk_synthesize_window_state (widget->window,
0,
GDK_WINDOW_STATE_WITHDRAWN);
}
else
GTK_WIDGET_CLASS (bin_class)->unmap (widget);
}
static void
gtk_plug_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
if (GTK_WIDGET_TOPLEVEL (widget))
GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
else
{
GtkBin *bin = GTK_BIN (widget);
if (GTK_WIDGET_REALIZED (widget))
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
{
GtkAllocation child_allocation;
child_allocation.x = child_allocation.y = GTK_CONTAINER (widget)->border_width;
child_allocation.width =
MAX (1, (gint)allocation->width - child_allocation.x * 2);
child_allocation.height =
MAX (1, (gint)allocation->height - child_allocation.y * 2);
gtk_widget_size_allocate (bin->child, &child_allocation);
}
}
} }
static gboolean static gboolean
@ -518,6 +706,15 @@ gtk_plug_focus (GtkWidget *widget,
return FALSE; return FALSE;
} }
static void
gtk_plug_check_resize (GtkContainer *container)
{
if (GTK_WIDGET_TOPLEVEL (container))
GTK_CONTAINER_CLASS (parent_class)->check_resize (container);
else
GTK_CONTAINER_CLASS (bin_class)->check_resize (container);
}
static void static void
send_xembed_message (GtkPlug *plug, send_xembed_message (GtkPlug *plug,
glong message, glong message,
@ -592,6 +789,25 @@ handle_modality_off (GtkPlug *plug)
} }
} }
static void
xembed_set_info (GdkWindow *gdk_window,
unsigned long flags)
{
Display *display = GDK_WINDOW_XDISPLAY (gdk_window);
Window window = GDK_WINDOW_XWINDOW (gdk_window);
unsigned long buffer[2];
Atom xembed_info_atom = gdk_atom_intern ("_XEMBED_INFO", FALSE);
buffer[1] = 0; /* Protocol version */
buffer[1] = flags;
XChangeProperty (display, window,
xembed_info_atom, xembed_info_atom, 32,
PropModeReplace,
(unsigned char *)buffer, 2);
}
static void static void
handle_xembed_message (GtkPlug *plug, handle_xembed_message (GtkPlug *plug,
glong message, glong message,

View File

@ -28,6 +28,7 @@
#include <gdk/gdk.h> #include <gdk/gdk.h>
#include <gtk/gtksocket.h>
#include <gtk/gtkwindow.h> #include <gtk/gtkwindow.h>
@ -55,7 +56,7 @@ struct _GtkPlug
GdkWindow *socket_window; GdkWindow *socket_window;
GtkWidget *modality_window; GtkWidget *modality_window;
GtkWindowGroup *modality_group; GtkWindowGroup *modality_group;
gboolean same_app; guint same_app : 1;
}; };
struct _GtkPlugClass struct _GtkPlugClass
@ -69,6 +70,9 @@ void gtk_plug_construct (GtkPlug *plug, GdkNativeWindow socket_id);
GtkWidget* gtk_plug_new (GdkNativeWindow socket_id); GtkWidget* gtk_plug_new (GdkNativeWindow socket_id);
void _gtk_plug_add_to_socket (GtkPlug *plug,
GtkSocket *socket);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@ -28,6 +28,7 @@
#include "gdk/gdkkeysyms.h" #include "gdk/gdkkeysyms.h"
#include "gtkmain.h" #include "gtkmain.h"
#include "gtkwindow.h" #include "gtkwindow.h"
#include "gtkplug.h"
#include "gtksignal.h" #include "gtksignal.h"
#include "gtksocket.h" #include "gtksocket.h"
#include "gtkdnd.h" #include "gtkdnd.h"
@ -60,6 +61,17 @@ static gboolean gtk_socket_focus_out_event (GtkWidget *widget
static void gtk_socket_send_configure_event (GtkSocket *socket); static void gtk_socket_send_configure_event (GtkSocket *socket);
static gboolean gtk_socket_focus (GtkWidget *widget, static gboolean gtk_socket_focus (GtkWidget *widget,
GtkDirectionType direction); GtkDirectionType direction);
static void gtk_socket_remove (GtkContainer *container,
GtkWidget *widget);
static void gtk_socket_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
gpointer callback_data);
static void gtk_socket_add_window (GtkSocket *socket,
GdkNativeWindow xid,
gboolean need_reparent);
static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent, static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent,
GdkEvent *event, GdkEvent *event,
gpointer data); gpointer data);
@ -70,6 +82,9 @@ static void send_xembed_message (GtkSocket *socket,
glong data1, glong data1,
glong data2, glong data2,
guint32 time); guint32 time);
static gboolean xembed_get_info (GdkWindow *gdk_window,
unsigned long *version,
unsigned long *flags);
/* From Tk */ /* From Tk */
#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
@ -124,8 +139,10 @@ gtk_socket_class_init (GtkSocketClass *class)
widget_class->key_press_event = gtk_socket_key_press_event; widget_class->key_press_event = gtk_socket_key_press_event;
widget_class->focus_in_event = gtk_socket_focus_in_event; widget_class->focus_in_event = gtk_socket_focus_in_event;
widget_class->focus_out_event = gtk_socket_focus_out_event; widget_class->focus_out_event = gtk_socket_focus_out_event;
widget_class->focus = gtk_socket_focus; widget_class->focus = gtk_socket_focus;
container_class->remove = gtk_socket_remove;
container_class->forall = gtk_socket_forall;
} }
static void static void
@ -137,7 +154,7 @@ gtk_socket_init (GtkSocket *socket)
socket->current_height = 0; socket->current_height = 0;
socket->plug_window = NULL; socket->plug_window = NULL;
socket->same_app = FALSE; socket->plug_widget = NULL;
socket->focus_in = FALSE; socket->focus_in = FALSE;
socket->have_size = FALSE; socket->have_size = FALSE;
socket->need_map = FALSE; socket->need_map = FALSE;
@ -156,57 +173,7 @@ gtk_socket_new (void)
void void
gtk_socket_steal (GtkSocket *socket, GdkNativeWindow id) gtk_socket_steal (GtkSocket *socket, GdkNativeWindow id)
{ {
GtkWidget *widget; gtk_socket_add_window (socket, id, TRUE);
gpointer user_data = NULL;
widget = GTK_WIDGET (socket);
socket->plug_window = gdk_window_lookup (id);
gdk_error_trap_push ();
if (socket->plug_window)
gdk_window_get_user_data (socket->plug_window,
&user_data);
if (user_data)
{
/*
GtkWidget *child_widget;
child_widget = GTK_WIDGET (socket->plug_window->user_data);
*/
g_warning("Stealing from same app not yet implemented");
socket->same_app = TRUE;
}
else
{
socket->plug_window = gdk_window_foreign_new (id);
if (!socket->plug_window) /* was deleted before we could get it */
{
gdk_error_trap_pop ();
return;
}
socket->same_app = FALSE;
socket->have_size = FALSE;
XSelectInput (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW(socket->plug_window),
StructureNotifyMask | PropertyChangeMask);
gtk_widget_queue_resize (widget);
}
gdk_window_hide (socket->plug_window);
gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
gdk_flush ();
gdk_error_trap_pop ();
socket->need_map = TRUE;
} }
static void static void
@ -307,7 +274,13 @@ gtk_socket_size_request (GtkWidget *widget,
socket = GTK_SOCKET (widget); socket = GTK_SOCKET (widget);
if (!socket->have_size && socket->plug_window) if (socket->plug_widget)
{
gtk_widget_size_request (socket->plug_widget, requisition);
}
else
{
if (socket->is_mapped && !socket->have_size && socket->plug_window)
{ {
XSizeHints hints; XSizeHints hints;
long supplied; long supplied;
@ -341,9 +314,18 @@ gtk_socket_size_request (GtkWidget *widget,
gdk_error_trap_pop (); gdk_error_trap_pop ();
} }
if (socket->is_mapped && socket->have_size)
{
requisition->width = MAX (socket->request_width, 1); requisition->width = MAX (socket->request_width, 1);
requisition->height = MAX (socket->request_height, 1); requisition->height = MAX (socket->request_height, 1);
} }
else
{
requisition->width = 1;
requisition->height = 1;
}
}
}
static void static void
gtk_socket_size_allocate (GtkWidget *widget, gtk_socket_size_allocate (GtkWidget *widget,
@ -364,7 +346,18 @@ gtk_socket_size_allocate (GtkWidget *widget,
allocation->x, allocation->y, allocation->x, allocation->y,
allocation->width, allocation->height); allocation->width, allocation->height);
if (socket->plug_window) if (socket->plug_widget)
{
GtkAllocation child_allocation;
child_allocation.x = 0;
child_allocation.y = 0;
child_allocation.width = allocation->width;
child_allocation.height = allocation->height;
gtk_widget_size_allocate (socket->plug_widget, &child_allocation);
}
else if (socket->plug_window)
{ {
gdk_error_trap_push (); gdk_error_trap_push ();
@ -652,9 +645,9 @@ gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
#if 0 #if 0
GtkWidget *toplevel; GtkWidget *toplevel;
toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); toplevel = gtk_widget_get_toplevel (widget);
if (toplevel) if (toplevel && GTK_IS_WINDOW (toplevel))
{ {
XSetInputFocus (GDK_DISPLAY (), XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (toplevel->window), GDK_WINDOW_XWINDOW (toplevel->window),
@ -711,6 +704,9 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
socket = GTK_SOCKET (widget); socket = GTK_SOCKET (widget);
if (socket->plug_widget)
return gtk_widget_child_focus (socket->plug_widget, direction);
if (!GTK_WIDGET_HAS_FOCUS (widget)) if (!GTK_WIDGET_HAS_FOCUS (widget))
{ {
switch (direction) switch (direction)
@ -799,6 +795,39 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
#endif #endif
} }
static void
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));
}
static void
gtk_socket_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
gpointer callback_data)
{
GtkSocket *socket = GTK_SOCKET (container);
if (socket->plug_widget)
(* callback) (socket->plug_widget, callback_data);
}
static void static void
gtk_socket_send_configure_event (GtkSocket *socket) gtk_socket_send_configure_event (GtkSocket *socket)
{ {
@ -830,30 +859,98 @@ gtk_socket_send_configure_event (GtkSocket *socket)
} }
static void static void
gtk_socket_add_window (GtkSocket *socket, GdkNativeWindow xid) gtk_socket_add_window (GtkSocket *socket,
GdkNativeWindow xid,
gboolean need_reparent)
{ {
socket->plug_window = gdk_window_lookup (xid);
socket->same_app = TRUE;
if (!socket->plug_window) GtkWidget *widget = GTK_WIDGET (socket);
gpointer user_data = NULL;
socket->plug_window = gdk_window_lookup (xid);
if (socket->plug_window)
{
g_object_ref (socket->plug_window);
gdk_window_get_user_data (socket->plug_window, &user_data);
}
if (user_data) /* A widget's window in this process */
{
GtkWidget *child_widget = user_data;
if (!GTK_IS_PLUG (child_widget))
{
g_warning (G_STRLOC "Can't add non-GtkPlug to GtkSocket");
socket->plug_window = NULL;
gdk_error_trap_pop ();
return;
}
_gtk_plug_add_to_socket (GTK_PLUG (child_widget), socket);
}
else /* A foreign window */
{ {
GtkWidget *toplevel; GtkWidget *toplevel;
GdkDragProtocol protocol; GdkDragProtocol protocol;
unsigned long version;
socket->plug_window = gdk_window_foreign_new (xid); unsigned long flags;
if (!socket->plug_window) /* Already gone */
return;
socket->same_app = FALSE;
gdk_error_trap_push (); gdk_error_trap_push ();
if (!socket->plug_window)
{
socket->plug_window = gdk_window_foreign_new (xid);
if (!socket->plug_window) /* was deleted before we could get it */
{
gdk_error_trap_pop ();
return;
}
}
XSelectInput (GDK_DISPLAY (), XSelectInput (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW(socket->plug_window), GDK_WINDOW_XWINDOW(socket->plug_window),
StructureNotifyMask | PropertyChangeMask); StructureNotifyMask | PropertyChangeMask);
if (gdk_error_trap_pop ())
{
gdk_window_unref (socket->plug_window);
socket->plug_window = NULL;
return;
}
/* OK, we now will reliably get destroy notification on socket->plug_window */
gdk_error_trap_push ();
if (need_reparent)
{
gdk_window_hide (socket->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */
gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
}
socket->have_size = FALSE;
socket->xembed_version = -1;
if (xembed_get_info (socket->plug_window, &version, &flags))
{
socket->xembed_version = version;
socket->is_mapped = (flags & XEMBED_MAPPED) != 0;
}
else
{
/* FIXME, we should probably actually check the state before we started */
socket->is_mapped = need_reparent ? TRUE : FALSE;
}
socket->need_map = socket->is_mapped;
if (gdk_drag_get_protocol (xid, &protocol)) if (gdk_drag_get_protocol (xid, &protocol))
gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window, gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window,
protocol, TRUE); protocol, TRUE);
gdk_flush (); gdk_flush ();
gdk_error_trap_pop (); gdk_error_trap_pop ();
@ -864,9 +961,7 @@ gtk_socket_add_window (GtkSocket *socket, GdkNativeWindow xid)
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
if (toplevel && GTK_IS_WINDOW (toplevel)) if (toplevel && GTK_IS_WINDOW (toplevel))
{
gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid); gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
}
gtk_widget_queue_resize (GTK_WIDGET (socket)); gtk_widget_queue_resize (GTK_WIDGET (socket));
} }
@ -907,6 +1002,58 @@ send_xembed_message (GtkSocket *socket,
} }
} }
static gboolean
xembed_get_info (GdkWindow *gdk_window,
unsigned long *version,
unsigned long *flags)
{
Display *display = GDK_WINDOW_XDISPLAY (gdk_window);
Window window = GDK_WINDOW_XWINDOW (gdk_window);
Atom xembed_info_atom = gdk_atom_intern ("_XEMBED_INFO", FALSE);
Atom type;
int format;
unsigned long nitems, bytes_after;
unsigned char *data;
unsigned long *data_long;
int status;
gdk_error_trap_push();
status = XGetWindowProperty (display, window,
xembed_info_atom,
0, 2, False,
xembed_info_atom, &type, &format,
&nitems, &bytes_after, &data);
gdk_error_trap_pop();
if (status != Success)
return FALSE; /* Window vanished? */
if (type == None) /* No info property */
return FALSE;
if (type != xembed_info_atom)
{
g_warning ("_XEMBED_INFO property has wrong type\n");
return FALSE;
}
if (nitems < 2)
{
g_warning ("_XEMBED_INFO too short\n");
XFree (data);
return FALSE;
}
data_long = (unsigned long *)data;
if (version)
*version = data_long[0];
if (flags)
*flags = data_long[1] & XEMBED_MAPPED;
XFree (data);
return TRUE;
}
static void static void
handle_xembed_message (GtkSocket *socket, handle_xembed_message (GtkSocket *socket,
glong message, glong message,
@ -962,6 +1109,28 @@ handle_xembed_message (GtkSocket *socket,
} }
} }
static void
map_request (GtkSocket *socket)
{
if (!socket->is_mapped)
{
socket->is_mapped = TRUE;
socket->need_map = TRUE;
gtk_widget_queue_resize (GTK_WIDGET (socket));
}
}
static void
unmap_notify (GtkSocket *socket)
{
if (socket->is_mapped)
{
socket->is_mapped = FALSE;
gtk_widget_queue_resize (GTK_WIDGET (socket));
}
}
static GdkFilterReturn static GdkFilterReturn
gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
{ {
@ -977,16 +1146,35 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
return_val = GDK_FILTER_CONTINUE; return_val = GDK_FILTER_CONTINUE;
if (socket->plug_widget)
return return_val;
switch (xevent->type) switch (xevent->type)
{ {
case ClientMessage:
if (xevent->xclient.message_type == gdk_atom_intern ("_XEMBED", FALSE))
{
handle_xembed_message (socket,
xevent->xclient.data.l[1],
xevent->xclient.data.l[2],
xevent->xclient.data.l[3],
xevent->xclient.data.l[4],
xevent->xclient.data.l[0]);
return_val = GDK_FILTER_REMOVE;
}
break;
case CreateNotify: case CreateNotify:
{ {
XCreateWindowEvent *xcwe = &xevent->xcreatewindow; XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
if (!socket->plug_window) if (!socket->plug_window)
{ gtk_socket_add_window (socket, xcwe->window, FALSE);
gtk_socket_add_window (socket, xcwe->window);
if (socket->plug_window)
{
gdk_error_trap_push (); gdk_error_trap_push ();
gdk_window_move_resize(socket->plug_window, gdk_window_move_resize(socket->plug_window,
0, 0, 0, 0,
@ -1015,9 +1203,9 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
XConfigureRequestEvent *xcre = &xevent->xconfigurerequest; XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
if (!socket->plug_window) if (!socket->plug_window)
gtk_socket_add_window (socket, xcre->window); gtk_socket_add_window (socket, xcre->window, FALSE);
if (xcre->window == GDK_WINDOW_XWINDOW (socket->plug_window)) if (socket->plug_window)
{ {
if (xcre->value_mask & (CWWidth | CWHeight)) if (xcre->value_mask & (CWWidth | CWHeight))
{ {
@ -1047,8 +1235,7 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
{ {
XDestroyWindowEvent *xdwe = &xevent->xdestroywindow; XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
if (socket->plug_window && if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
(xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
{ {
GtkWidget *toplevel; GtkWidget *toplevel;
@ -1078,9 +1265,9 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
{ {
#if 0 #if 0
GtkWidget *toplevel; GtkWidget *toplevel;
toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); toplevel = gtk_widget_get_toplevel (widget);
if (toplevel) if (toplevel && GTK_IS_WINDOW (topelevel))
{ {
XSetInputFocus (GDK_DISPLAY (), XSetInputFocus (GDK_DISPLAY (),
GDK_WINDOW_XWINDOW (toplevel->window), GDK_WINDOW_XWINDOW (toplevel->window),
@ -1095,25 +1282,20 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
break; break;
case MapRequest: case MapRequest:
if (!socket->plug_window) if (!socket->plug_window)
gtk_socket_add_window (socket, xevent->xmaprequest.window); gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE);
if (xevent->xmaprequest.window == if (socket->plug_window)
GDK_WINDOW_XWINDOW (socket->plug_window))
{ {
GTK_NOTE(PLUGSOCKET, GTK_NOTE(PLUGSOCKET,
g_message ("GtkSocket - Map Request")); g_message ("GtkSocket - Map Request"));
gdk_error_trap_push (); map_request (socket);
gdk_window_show (socket->plug_window);
gdk_flush ();
gdk_error_trap_pop ();
return_val = GDK_FILTER_REMOVE; return_val = GDK_FILTER_REMOVE;
} }
break; break;
case PropertyNotify: case PropertyNotify:
if (xevent->xproperty.window == if (socket->plug_window &&
GDK_WINDOW_XWINDOW (socket->plug_window)) xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window))
{ {
GdkDragProtocol protocol; GdkDragProtocol protocol;
@ -1128,23 +1310,47 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
gdk_flush (); gdk_flush ();
gdk_error_trap_pop (); gdk_error_trap_pop ();
} }
return_val = GDK_FILTER_REMOVE; else if (xevent->xproperty.atom == gdk_atom_intern ("_XEMBED_INFO", FALSE))
}
break;
case ClientMessage:
if (xevent->xclient.message_type == gdk_atom_intern ("_XEMBED", FALSE))
{ {
handle_xembed_message (socket, unsigned long flags;
xevent->xclient.data.l[1],
xevent->xclient.data.l[2],
xevent->xclient.data.l[3],
xevent->xclient.data.l[4],
xevent->xclient.data.l[0]);
if (xembed_get_info (socket->plug_window, NULL, &flags))
{
gboolean was_mapped = socket->is_mapped;
gboolean is_mapped = (flags & XEMBED_MAPPED) != 0;
if (was_mapped != is_mapped)
{
if (is_mapped)
map_request (socket);
else
{
gdk_error_trap_push ();
gdk_window_show (socket->plug_window);
gdk_flush ();
gdk_error_trap_pop ();
unmap_notify (socket);
}
}
}
}
return_val = GDK_FILTER_REMOVE; return_val = GDK_FILTER_REMOVE;
} }
break; break;
case UnmapNotify:
if (socket->plug_window &&
xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window))
{
GTK_NOTE(PLUGSOCKET,
g_message ("GtkSocket - Unmap notify"));
unmap_notify (socket);
return_val = GDK_FILTER_REMOVE;
}
break;
} }
return return_val; return return_val;

View File

@ -54,10 +54,14 @@ struct _GtkSocket
guint16 current_height; guint16 current_height;
GdkWindow *plug_window; GdkWindow *plug_window;
GtkWidget *plug_widget;
gshort xembed_version; /* -1 == not xembed */
guint same_app : 1; guint same_app : 1;
guint focus_in : 1; guint focus_in : 1;
guint have_size : 1; guint have_size : 1;
guint need_map : 1; guint need_map : 1;
guint is_mapped : 1;
GHashTable *grabbed_keys; GHashTable *grabbed_keys;
GtkWidget *toplevel; GtkWidget *toplevel;

View File

@ -4550,7 +4550,19 @@ gtk_widget_set_extension_events (GtkWidget *widget,
* *
* Note the difference in behavior vs. gtk_widget_get_ancestor(); * Note the difference in behavior vs. gtk_widget_get_ancestor();
* gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) would return * gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW) would return
* %NULL if @widget wasn't inside a toplevel window. * %NULL if @widget wasn't inside a toplevel window, and if the
* window was inside a GtkWindow-derived widget which was in turn
* inside the toplevel GtkWindow. While the second case may
* 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
*
* GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
* if (GTK_IS_WINDOW (toplevel))
* {
* /* Perform action on toplevel.
* }
* *
* Return value: the topmost ancestor of @widget, or @widget itself if there's no ancestor * Return value: the topmost ancestor of @widget, or @widget itself if there's no ancestor
**/ **/
@ -4574,7 +4586,8 @@ gtk_widget_get_toplevel (GtkWidget *widget)
* Gets the first ancestor of @widget with type @widget_type. For example, * Gets the first ancestor of @widget with type @widget_type. For example,
* gtk_widget_get_ancestor (widget, GTK_TYPE_BOX) gets the first #GtkBox that's * gtk_widget_get_ancestor (widget, GTK_TYPE_BOX) gets the first #GtkBox that's
* an ancestor of @widget. No reference will be added to the returned widget; * an ancestor of @widget. No reference will be added to the returned widget;
* it should not be unreferenced. * it should not be unreferenced. See note about checking for a toplevel
* GtkWindow in the docs for gtk_widget_get_toplevel().
* *
* Return value: the ancestor widget, or %NULL if not found * Return value: the ancestor widget, or %NULL if not found
**/ **/

View File

@ -17,3 +17,6 @@
#define XEMBED_FOCUS_FIRST 1 #define XEMBED_FOCUS_FIRST 1
#define XEMBED_FOCUS_LAST 2 #define XEMBED_FOCUS_LAST 2
/* Flags for _XEMBED_INFO */
#define XEMBED_MAPPED (1 << 0)

View File

@ -87,6 +87,14 @@ testtext_SOURCES = \
prop-editor.c \ prop-editor.c \
testtext.c testtext.c
testsocket_SOURCES = \
testsocket.c \
testsocket_common.c
testsocket_child_SOURCES = \
testsocket_child.c \
testsocket_common.c
EXTRA_DIST += @STRIP_BEGIN@ \ EXTRA_DIST += @STRIP_BEGIN@ \
prop-editor.h \ prop-editor.h \
testgtk.1 \ testgtk.1 \

View File

@ -10,11 +10,17 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
int n_children = 0;
GtkWidget *window; GtkWidget *window;
GtkWidget *vbox; GtkWidget *vbox;
GtkWidget *lastsocket = NULL; GtkWidget *lastsocket = NULL;
extern guint32 create_child_plug (guint32 xid,
gboolean local);
static void static void
quit_cb (gpointer callback_data, quit_cb (gpointer callback_data,
guint callback_action, guint callback_action,
@ -69,12 +75,61 @@ remove_child (GtkWidget *window)
lastsocket = NULL; lastsocket = NULL;
} }
static gboolean
child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data)
{
GIOStatus status;
GError *error = NULL;
char *line;
gsize term;
int xid;
status = g_io_channel_read_line (channel, &line, NULL, &term, &error);
switch (status)
{
case G_IO_STATUS_NORMAL:
line[term] = '\0';
xid = strtol (line, NULL, 0);
if (xid == 0)
{
fprintf (stderr, "Invalid window id '%s'\n", line);
}
else
{
GtkWidget *socket = gtk_socket_new ();
gtk_box_pack_start (GTK_BOX (vbox), socket, TRUE, TRUE, 0);
gtk_widget_show (socket);
gtk_socket_steal (GTK_SOCKET (socket), xid);
}
g_free (line);
return TRUE;
case G_IO_STATUS_AGAIN:
return TRUE;
case G_IO_STATUS_EOF:
n_children--;
g_io_channel_close (channel);
return FALSE;
case G_IO_STATUS_ERROR:
fprintf (stderr, "Error reading fd from child: %s\n", error->message);
exit (1);
return FALSE;
default:
g_assert_not_reached ();
return FALSE;
}
}
void void
add_child (GtkWidget *window) add_child (GtkWidget *window,
gboolean active)
{ {
GtkWidget *socket; GtkWidget *socket;
char *argv[3] = { "./testsocket_child", NULL, NULL }; char *argv[3] = { "./testsocket_child", NULL, NULL };
char buffer[20]; char buffer[20];
int out_fd;
GIOChannel *channel;
GError *error = NULL; GError *error = NULL;
socket = gtk_socket_new (); socket = gtk_socket_new ();
@ -83,20 +138,61 @@ add_child (GtkWidget *window)
lastsocket = socket; lastsocket = socket;
if (active)
{
sprintf(buffer, "%#lx", GDK_WINDOW_XWINDOW (socket->window)); sprintf(buffer, "%#lx", GDK_WINDOW_XWINDOW (socket->window));
argv[1] = buffer; argv[1] = buffer;
}
#if 1 #if 1
if (!g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &error)) 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); fprintf (stderr, "Can't exec testsocket_child: %s\n", error->message);
exit (1); exit (1);
} }
n_children++;
channel = g_io_channel_unix_new (out_fd);
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, &error);
if (error)
{
fprintf (stderr, "Error making channel non-blocking: %s\n", error->message);
exit (1);
}
g_io_add_watch (channel, G_IO_IN | G_IO_HUP, child_read_watch, NULL);
#else #else
fprintf(stderr,"%s\n", buffer); fprintf(stderr,"%s\n", buffer);
#endif #endif
} }
void
add_active_child (GtkWidget *window)
{
add_child (window, TRUE);
}
void
add_passive_child (GtkWidget *window)
{
add_child (window, FALSE);
}
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);
lastsocket = socket;
create_child_plug (GDK_WINDOW_XWINDOW (socket->window), TRUE);
}
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
@ -131,11 +227,25 @@ main (int argc, char *argv[])
gtk_item_factory_get_widget (item_factory, "<main>"), gtk_item_factory_get_widget (item_factory, "<main>"),
FALSE, FALSE, 0); FALSE, FALSE, 0);
button = gtk_button_new_with_label ("Add Child"); button = gtk_button_new_with_label ("Add Active Child");
gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
gtk_signal_connect_object (GTK_OBJECT(button), "clicked", gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(add_child), GTK_SIGNAL_FUNC(add_active_child),
GTK_OBJECT(vbox));
button = gtk_button_new_with_label ("Add Passive Child");
gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(add_passive_child),
GTK_OBJECT(vbox));
button = gtk_button_new_with_label ("Add Local Child");
gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(add_local_child),
GTK_OBJECT(vbox)); GTK_OBJECT(vbox));
button = gtk_button_new_with_label ("Remove Last Child"); button = gtk_button_new_with_label ("Remove Last Child");
@ -162,7 +272,13 @@ main (int argc, char *argv[])
gtk_main (); gtk_main ();
return 0; if (n_children)
{
g_print ("Waiting for children to exit\n");
while (n_children)
g_main_iteration (TRUE);
} }
return 0;
}

View File

@ -3,53 +3,25 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
void extern guint32 create_child_plug (guint32 xid,
remove_buttons (GtkWidget *widget, GtkWidget *other_button) gboolean local);
{
gtk_widget_destroy (other_button);
gtk_widget_destroy (widget);
}
void
add_buttons (GtkWidget *widget, GtkWidget *box)
{
GtkWidget *add_button;
GtkWidget *remove_button;
add_button = gtk_button_new_with_mnemonic ("_Add");
gtk_box_pack_start (GTK_BOX (box), add_button, TRUE, TRUE, 0);
gtk_widget_show (add_button);
gtk_signal_connect (GTK_OBJECT (add_button), "clicked",
GTK_SIGNAL_FUNC (add_buttons),
box);
remove_button = gtk_button_new_with_mnemonic ("_Remove");
gtk_box_pack_start (GTK_BOX (box), remove_button, TRUE, TRUE, 0);
gtk_widget_show (remove_button);
gtk_signal_connect (GTK_OBJECT (remove_button), "clicked",
GTK_SIGNAL_FUNC (remove_buttons),
add_button);
}
int int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
guint32 xid; guint32 xid;
guint32 plug_xid;
GtkWidget *window;
GtkWidget *hbox;
GtkWidget *entry;
GtkWidget *button;
gtk_init (&argc, &argv); gtk_init (&argc, &argv);
if (argc < 2) if (argc != 1 && argc != 2)
{ {
fprintf (stderr, "Usage: testsocket_child WINDOW_ID\n"); fprintf (stderr, "Usage: testsocket_child [WINDOW_ID]\n");
exit (1); exit (1);
} }
if (argc == 2)
{
xid = strtol (argv[1], NULL, 0); xid = strtol (argv[1], NULL, 0);
if (xid == 0) if (xid == 0)
{ {
@ -57,30 +29,14 @@ main (int argc, char *argv[])
exit (1); exit (1);
} }
window = gtk_plug_new (xid); create_child_plug (xid, FALSE);
gtk_signal_connect (GTK_OBJECT (window), "destroy", }
(GtkSignalFunc) gtk_exit, NULL); else
gtk_container_set_border_width (GTK_CONTAINER (window), 0); {
plug_xid = create_child_plug (0, FALSE);
hbox = gtk_hbox_new (FALSE, 0); printf ("%d\n", plug_xid);
gtk_container_add (GTK_CONTAINER (window), hbox); fflush (stdout);
gtk_widget_show (hbox); }
entry = gtk_entry_new ();
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
gtk_widget_show (entry);
button = gtk_button_new_with_mnemonic ("_Close");
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
gtk_widget_show (button);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (gtk_widget_destroy),
GTK_OBJECT (window));
add_buttons (NULL, hbox);
gtk_widget_show (window);
gtk_main (); gtk_main ();