summaryrefslogtreecommitdiffstats
path: root/xembed/tests
diff options
context:
space:
mode:
authorVincent Untz <vuntz@gnome.org>2012-03-02 15:36:01 +0100
committerVincent Untz <vuntz@gnome.org>2012-03-02 15:36:01 +0100
commit94db110fab0dcea1f8f87efce6ce1be15a67dfc7 (patch)
tree5e04297a2a3a811f9097de50160c4533887a141e /xembed/tests
parenta988ef565a037a39aecca754a2f9d2f43e5c5131 (diff)
parent23d7d60971b8428429f120cbf77f3fcf70304b67 (diff)
downloadxdg-specs-94db110fab0dcea1f8f87efce6ce1be15a67dfc7.tar.xz
xembed: Merge import from CVS
Diffstat (limited to 'xembed/tests')
-rw-r--r--xembed/tests/.cvsignore9
-rw-r--r--xembed/tests/Makefile.am39
-rw-r--r--xembed/tests/gtk-client.c202
-rw-r--r--xembed/tests/gtk-common.c182
-rw-r--r--xembed/tests/gtk-common.h22
-rw-r--r--xembed/tests/gtk-embedder.c163
-rw-r--r--xembed/tests/qt-client.cpp127
-rw-r--r--xembed/tests/qt-client.h34
-rw-r--r--xembed/tests/qt-common.cpp30
-rw-r--r--xembed/tests/qt-common.h10
-rw-r--r--xembed/tests/qt-embedder.cpp111
-rw-r--r--xembed/tests/qt-embedder.h28
12 files changed, 957 insertions, 0 deletions
diff --git a/xembed/tests/.cvsignore b/xembed/tests/.cvsignore
new file mode 100644
index 0000000..2bffb50
--- /dev/null
+++ b/xembed/tests/.cvsignore
@@ -0,0 +1,9 @@
+.deps
+.libs
+Makefile
+Makefile.in
+gtk-client
+gtk-embedder
+qt-client
+qt-embedder
+moc_*
diff --git a/xembed/tests/Makefile.am b/xembed/tests/Makefile.am
new file mode 100644
index 0000000..ecce952
--- /dev/null
+++ b/xembed/tests/Makefile.am
@@ -0,0 +1,39 @@
+noinst_PROGRAMS = qt-client qt-embedder gtk-client gtk-embedder
+
+INCLUDES = @all_includes@ @GTK_CFLAGS@ -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED
+
+#
+# Qt Examples
+#
+
+qt_libs = $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) $(LIB_KFILE) $(LIBSOCKET)
+
+BUILT_SOURCES=moc_qt-client.cpp moc_qt-embedder.cpp moc_qt-common.cpp
+
+moc_qt-client.cpp: qt-client.h
+ $(MOC) $< -o $@
+
+moc_qt-embedder.cpp: qt-embedder.h
+ $(MOC) $< -o $@
+
+moc_qt-common.cpp: qt-common.h
+ $(MOC) $< -o $@
+
+qt_client_SOURCES = qt-client.cpp qt-client.h qt-common.cpp qt-common.h
+qt_client_LDADD = $(qt_libs) moc_qt-client.$(OBJEXT) moc_qt-common.$(OBJEXT)
+
+qt_embedder_SOURCES = qt-embedder.cpp qt-embedder.h qt-common.cpp qt-common.h
+qt_embedder_LDADD = $(qt_libs) moc_qt-embedder.$(OBJEXT) moc_qt-common.$(OBJEXT)
+
+CLEANFILES = moc_qt-client.cpp moc_qt-embedder.cpp moc_qt-common.cpp
+
+#
+# GTK+ examples
+#
+
+gtk_client_SOURCES = gtk-client.c gtk-common.c gtk-common.h
+gtk_client_LDADD = $(GTK_LIBS)
+
+gtk_embedder_SOURCES = gtk-embedder.c gtk-common.c gtk-common.h
+gtk_embedder_LDADD = $(GTK_LIBS)
+
diff --git a/xembed/tests/gtk-client.c b/xembed/tests/gtk-client.c
new file mode 100644
index 0000000..e881d48
--- /dev/null
+++ b/xembed/tests/gtk-client.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gtk/gtk.h>
+
+#include "gtk-common.h"
+
+static void
+remove_buttons (GtkWidget *widget, GtkWidget *other_button)
+{
+ gtk_widget_destroy (other_button);
+ gtk_widget_destroy (widget);
+}
+
+static gboolean
+blink_cb (gpointer data)
+{
+ GtkWidget *widget = data;
+
+ gtk_widget_show (widget);
+ g_object_set_data (G_OBJECT (widget), "blink", GPOINTER_TO_UINT (0));
+
+ return FALSE;
+}
+
+static void
+blink (GtkWidget *widget,
+ GtkWidget *window)
+{
+ guint blink_timeout = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (window), "blink"));
+
+ if (!blink_timeout)
+ {
+ blink_timeout = g_timeout_add (1000, blink_cb, window);
+ gtk_widget_hide (window);
+
+ g_object_set_data (G_OBJECT (window), "blink", GUINT_TO_POINTER (blink_timeout));
+ }
+}
+
+static void
+remote_destroy (GtkWidget *window)
+{
+ guint blink_timeout = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (window), "blink"));
+ if (blink_timeout)
+ g_source_remove (blink_timeout);
+
+ gtk_main_quit ();
+}
+
+static 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);
+
+ g_signal_connect (add_button, "clicked",
+ G_CALLBACK (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);
+
+ g_signal_connect (remove_button, "clicked",
+ G_CALLBACK (remove_buttons), add_button);
+}
+
+void
+add_child (GtkWidget *vbox,
+ gboolean qt)
+{
+ Socket *socket = socket_new ();
+
+ gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
+ gtk_widget_show (socket->box);
+
+ socket_start_child (socket, FALSE, qt);
+}
+
+void
+add_gtk_child (GtkWidget *widget,
+ GtkWidget *vbox)
+{
+ add_child (vbox, FALSE);
+}
+
+void
+add_qt_child (GtkWidget *widget,
+ GtkWidget *vbox)
+{
+ add_child (vbox, TRUE);
+}
+
+guint32
+create_child_plug (guint32 xid)
+{
+ GtkWidget *window;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *entry;
+ GtkWidget *button;
+ GtkWidget *label;
+ GtkWidget *frame;
+
+ window = gtk_plug_new (xid);
+
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (window), frame);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (remote_destroy), NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+
+ label = gtk_label_new ("GTK+");
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+
+ entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+
+ button = gtk_button_new_with_mnemonic ("_Close");
+ gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+
+ g_signal_connect_swapped (button, "clicked",
+ G_CALLBACK (gtk_widget_destroy), window);
+
+ button = gtk_button_new_with_mnemonic ("_Blink");
+ gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (blink), window);
+
+ button = gtk_button_new_with_mnemonic ("Add _GTK+");
+ gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (add_gtk_child), vbox);
+
+ button = gtk_button_new_with_mnemonic ("Add _Qt");
+ gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (add_qt_child), vbox);
+
+ add_buttons (NULL, hbox);
+
+ gtk_widget_show_all (window);
+
+ if (GTK_WIDGET_REALIZED (window))
+ return gtk_plug_get_id (GTK_PLUG (window));
+ else
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ guint32 xid;
+ guint32 plug_xid;
+
+ gtk_init (&argc, &argv);
+
+ if (argc != 1 && argc != 2)
+ {
+ fprintf (stderr, "Usage: testsocket_child [WINDOW_ID]\n");
+ exit (1);
+ }
+
+ if (argc == 2)
+ {
+ xid = strtol (argv[1], NULL, 0);
+ if (xid == 0)
+ {
+ fprintf (stderr, "Invalid window id '%s'\n", argv[1]);
+ exit (1);
+ }
+
+ create_child_plug (xid);
+ }
+ else
+ {
+ plug_xid = create_child_plug (0);
+ printf ("%d\n", plug_xid);
+ fflush (stdout);
+ }
+
+ gtk_main ();
+
+ wait_for_children ();
+
+ return 0;
+}
+
+
diff --git a/xembed/tests/gtk-common.c b/xembed/tests/gtk-common.c
new file mode 100644
index 0000000..abb2294
--- /dev/null
+++ b/xembed/tests/gtk-common.c
@@ -0,0 +1,182 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+
+#include "gtk-common.h"
+
+static int n_children = 0;
+
+struct _Child
+{
+ Socket *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 void
+socket_destroy (GtkWidget *widget,
+ Socket *socket)
+{
+ if (socket->child)
+ socket->child->socket = NULL;
+ g_free (socket);
+}
+
+Socket *
+socket_new (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);
+
+ g_signal_connect (socket->socket, "plug_added",
+ G_CALLBACK (plug_added), socket);
+ g_signal_connect (socket->socket, "plug_removed",
+ G_CALLBACK (plug_removed), socket);
+ g_signal_connect_after (socket->socket, "destroy",
+ G_CALLBACK (socket_destroy), socket);
+
+ socket->child = NULL;
+
+ return socket;
+}
+
+static gboolean
+child_read_watch (GIOChannel *channel, GIOCondition cond, gpointer data)
+{
+ GIOStatus status;
+ GError *error = NULL;
+ Child *child = data;
+ char *line;
+ gsize term;
+ int xid;
+
+ status = g_io_channel_read_line (channel, &line, NULL, &term, &error);
+ switch (status)
+ {
+ case G_IO_STATUS_NORMAL:
+ if (child->socket && !GTK_SOCKET (child->socket->socket)->plug_window)
+ {
+ line[term] = '\0';
+ xid = strtol (line, NULL, 0);
+ if (xid == 0)
+ {
+ fprintf (stderr, "Invalid window id '%s'\n", line);
+ }
+ else
+ {
+ gtk_socket_add_id (GTK_SOCKET (child->socket->socket), xid);
+ }
+ }
+ g_free (line);
+ return TRUE;
+ case G_IO_STATUS_AGAIN:
+ return TRUE;
+ case G_IO_STATUS_EOF:
+ n_children--;
+ if (child->socket)
+ child->socket->child = NULL;
+ g_free (child);
+ g_io_channel_shutdown (channel, FALSE, NULL);
+ 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
+socket_start_child (Socket *socket,
+ gboolean active,
+ gboolean qt)
+{
+ char *argv[3] = { NULL, NULL, NULL };
+ char buffer[20];
+ int out_fd;
+ GIOChannel *channel;
+ GError *error = NULL;
+
+ socket->child = g_new (Child, 1);
+ socket->child->socket = socket;
+
+ argv[0] = qt ? "./qt-client" : "./gtk-client";
+
+ if (active)
+ {
+ sprintf(buffer, "%#lx", (gulong) gtk_socket_get_id (GTK_SOCKET (socket->socket)));
+ argv[1] = buffer;
+ }
+
+ if (!g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, &out_fd, NULL, &error))
+ {
+ fprintf (stderr, "Can't exec %s: %s\n", argv[0], error->message);
+ 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, socket->child);
+ g_io_channel_unref (channel);
+}
+
+void
+wait_for_children ()
+{
+ if (n_children)
+ {
+ g_print ("Waiting for children to exit\n");
+
+ while (n_children)
+ g_main_context_iteration (NULL, TRUE);
+ }
+
+}
diff --git a/xembed/tests/gtk-common.h b/xembed/tests/gtk-common.h
new file mode 100644
index 0000000..ac77d46
--- /dev/null
+++ b/xembed/tests/gtk-common.h
@@ -0,0 +1,22 @@
+typedef struct _Child Child;
+typedef struct _Socket Socket;
+
+struct _Socket
+{
+ GtkWidget *box;
+ GtkWidget *frame;
+ GtkWidget *socket;
+
+ Child *child;
+};
+
+
+void wait_for_children (void);
+
+Socket *socket_new (void);
+void socket_start_child (Socket *socket,
+ gboolean active,
+ gboolean qt);
+
+
+
diff --git a/xembed/tests/gtk-embedder.c b/xembed/tests/gtk-embedder.c
new file mode 100644
index 0000000..d3a7495
--- /dev/null
+++ b/xembed/tests/gtk-embedder.c
@@ -0,0 +1,163 @@
+#include <gtk/gtk.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "gtk-common.h"
+
+GSList *sockets = NULL;
+
+GtkWidget *window;
+GtkWidget *vbox;
+
+static void
+quit_cb (gpointer callback_data,
+ guint callback_action,
+ GtkWidget *widget)
+{
+ GtkWidget *message_dialog = gtk_message_dialog_new (GTK_WINDOW (window), 0,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ "Really Quit?");
+ gtk_dialog_add_buttons (GTK_DIALOG (message_dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_QUIT, GTK_RESPONSE_YES,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (message_dialog), GTK_RESPONSE_YES);
+
+ if (gtk_dialog_run (GTK_DIALOG (message_dialog)) == GTK_RESPONSE_YES)
+ gtk_widget_destroy (window);
+
+ gtk_widget_destroy (message_dialog);
+}
+
+static GtkItemFactoryEntry menu_items[] =
+{
+ { "/_File", NULL, 0, 0, "<Branch>" },
+ { "/File/_Quit", "<control>Q", quit_cb, 0 },
+};
+
+static void
+socket_destroyed (GtkWidget *widget,
+ Socket *socket)
+{
+ sockets = g_slist_remove (sockets, socket);
+}
+
+static void
+remove_child (void)
+{
+ if (sockets)
+ {
+ Socket *socket = sockets->data;
+ gtk_widget_destroy (socket->box);
+ }
+}
+
+void
+add_child (gboolean active,
+ gboolean qt)
+{
+ Socket *socket = socket_new ();
+
+ gtk_box_pack_start (GTK_BOX (vbox), socket->box, TRUE, TRUE, 0);
+ gtk_widget_show (socket->box);
+
+ sockets = g_slist_prepend (sockets, socket);
+
+ socket_start_child (socket, active, qt);
+
+ g_signal_connect (socket->socket, "destroy",
+ G_CALLBACK (socket_destroyed), socket);
+}
+
+void
+add_active_gtk_child (void)
+{
+ add_child (TRUE, FALSE);
+}
+
+void
+add_passive_gtk_child (void)
+{
+ add_child (FALSE, FALSE);
+}
+
+void
+add_active_qt_child (void)
+{
+ add_child (TRUE, TRUE);
+}
+
+void
+add_passive_qt_child (void)
+{
+ add_child (FALSE, TRUE);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *button;
+ GtkWidget *hbox;
+ GtkAccelGroup *accel_group;
+ GtkItemFactory *item_factory;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (gtk_main_quit), NULL);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Socket Test");
+ gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ accel_group = gtk_accel_group_new ();
+ gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+ item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
+
+
+ gtk_item_factory_create_items (item_factory,
+ G_N_ELEMENTS (menu_items), menu_items,
+ NULL);
+
+ gtk_box_pack_start (GTK_BOX (vbox),
+ gtk_item_factory_get_widget (item_factory, "<main>"),
+ FALSE, FALSE, 0);
+
+ button = gtk_button_new_with_label ("Add Active Qt Child");
+ gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
+ g_signal_connect (button, "clicked", G_CALLBACK (add_active_qt_child), NULL);
+
+ button = gtk_button_new_with_label ("Add Passive Qt Child");
+ gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
+ g_signal_connect (button, "clicked", GTK_SIGNAL_FUNC (add_passive_qt_child), NULL);
+
+ button = gtk_button_new_with_label ("Add Active GTK+ Child");
+ gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
+ g_signal_connect (button, "clicked", G_CALLBACK (add_active_gtk_child), NULL);
+
+ button = gtk_button_new_with_label ("Add Passive GTK+ Child");
+ gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
+ g_signal_connect (button, "clicked", G_CALLBACK (add_passive_gtk_child), NULL);
+
+ button = gtk_button_new_with_label ("Remove Last Child");
+ gtk_box_pack_start (GTK_BOX(vbox), button, FALSE, FALSE, 0);
+ g_signal_connect (button, "clicked", G_CALLBACK (remove_child), NULL);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ wait_for_children ();
+
+ return 0;
+}
diff --git a/xembed/tests/qt-client.cpp b/xembed/tests/qt-client.cpp
new file mode 100644
index 0000000..ef40739
--- /dev/null
+++ b/xembed/tests/qt-client.cpp
@@ -0,0 +1,127 @@
+#include <kapp.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+
+#include <qxembed.h>
+
+#include "qt-client.h"
+#include "qt-common.h"
+
+XEmbedQtButtonBox::XEmbedQtButtonBox (QWidget *parent, XEmbedQtClient *client)
+ : QWidget (parent)
+{
+ QHBoxLayout *layout = new QHBoxLayout (this);
+ layout->setAutoAdd (TRUE);
+
+ QPushButton *button;
+
+ button = new QPushButton( "&Add", this );
+ QObject::connect (button, SIGNAL(clicked()), client, SLOT(addButtons()));
+
+ button = new QPushButton( "&Remove", this );
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(close()));
+}
+
+
+XEmbedQtClient::XEmbedQtClient ()
+{
+ setFrameStyle (QFrame::Box | QFrame::Sunken);
+
+ QVBoxLayout *vlayout = new QVBoxLayout (this);
+
+ vlayout->setAutoAdd (TRUE);
+ vlayout->setMargin (5);
+
+ hbox_ = new QHBox (this);
+
+ new QLabel ("Qt", hbox_);
+
+ new QLineEdit (hbox_);
+
+ QPushButton *button;
+
+ button = new QPushButton( "&Close", hbox_ );
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(close()));
+
+ button = new QPushButton( "&Blink", hbox_ );
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(blink()));
+
+ button = new QPushButton( "Add &GTK+", hbox_ );
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(addGtkChild()));
+
+ button = new QPushButton( "Add &Qt", hbox_ );
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(addQtChild()));
+
+ addButtons();
+}
+
+void
+XEmbedQtClient::blink()
+{
+ hide ();
+
+ QTimer *timer = new QTimer ( this );
+ QObject::connect (timer, SIGNAL(timeout()), this, SLOT(show()));
+ timer->start (1000, TRUE);
+}
+
+void
+XEmbedQtClient::addGtkChild()
+{
+ new XEmbedQtChildSite (this, FALSE, FALSE);
+}
+
+void
+XEmbedQtClient::addQtChild()
+{
+ new XEmbedQtChildSite (this, FALSE, TRUE);
+}
+
+void
+XEmbedQtClient::addButtons ()
+{
+ XEmbedQtButtonBox *box = new XEmbedQtButtonBox (hbox_, this);
+ box->show();
+}
+
+int main( int argc, char **argv )
+{
+ KApplication a( argc, argv, "qt-client" );
+ WId embedder_xid, client_xid;
+ XEmbedQtClient *client;
+
+ if (argc != 1 && argc != 2)
+ {
+ fprintf (stderr, "Usage: qt-client [WINDOW_ID]\n");
+ exit (1);
+ }
+
+ QXEmbed::initialize ();
+
+ if (argc == 2)
+ {
+ embedder_xid = strtol (argv[1], NULL, 0);
+ if (embedder_xid == 0)
+ {
+ fprintf (stderr, "Invalid window id '%s'\n", argv[1]);
+ exit (1);
+ }
+
+ client = new XEmbedQtClient ();
+ QXEmbed::embedClientIntoWindow (client, embedder_xid);
+ }
+ else
+ {
+ client = new XEmbedQtClient ();
+ printf ("%d\n", client->winId());
+ fflush (stdout);
+ }
+
+ a.setMainWidget( client );
+
+ return a.exec();
+}
diff --git a/xembed/tests/qt-client.h b/xembed/tests/qt-client.h
new file mode 100644
index 0000000..0ec1d66
--- /dev/null
+++ b/xembed/tests/qt-client.h
@@ -0,0 +1,34 @@
+#include <qframe.h>
+
+class QHBox;
+
+class XEmbedQtClient;
+
+class XEmbedQtButtonBox : public QWidget
+{
+ Q_OBJECT
+
+ public:
+
+ XEmbedQtButtonBox (QWidget *parent, XEmbedQtClient *client);
+};
+
+class XEmbedQtClient : public QFrame
+{
+ Q_OBJECT
+
+ public:
+
+ XEmbedQtClient ();
+
+ public slots:
+ void addButtons ();
+
+ private:
+ QHBox *hbox_;
+
+ private slots:
+ void blink();
+ void addGtkChild();
+ void addQtChild();
+};
diff --git a/xembed/tests/qt-common.cpp b/xembed/tests/qt-common.cpp
new file mode 100644
index 0000000..9021d7e
--- /dev/null
+++ b/xembed/tests/qt-common.cpp
@@ -0,0 +1,30 @@
+#include "qt-common.h"
+
+#include <qprocess.h>
+
+XEmbedQtChildSite::XEmbedQtChildSite (QWidget *parent, bool active, bool isQt)
+ : QXEmbed (parent)
+{
+ show ();
+
+ QProcess *proc = new QProcess (this);
+
+ proc->setCommunication (QProcess::Stdout);
+
+ if (isQt)
+ proc->addArgument ("./qt-client");
+ else
+ proc->addArgument ("./gtk-client");
+
+ if (active)
+ proc->addArgument (QString::number (winId ()));
+
+ proc->start ();
+
+ if (!active)
+ {
+ QString pid_str = proc->readLineStdout ();
+ embed (pid_str.toLong ());
+ }
+}
+
diff --git a/xembed/tests/qt-common.h b/xembed/tests/qt-common.h
new file mode 100644
index 0000000..28cc56f
--- /dev/null
+++ b/xembed/tests/qt-common.h
@@ -0,0 +1,10 @@
+#include <qxembed.h>
+
+class XEmbedQtChildSite : public QXEmbed
+{
+ Q_OBJECT
+
+ public:
+
+ XEmbedQtChildSite (QWidget *parent, bool active, bool isQt);
+};
diff --git a/xembed/tests/qt-embedder.cpp b/xembed/tests/qt-embedder.cpp
new file mode 100644
index 0000000..e004204
--- /dev/null
+++ b/xembed/tests/qt-embedder.cpp
@@ -0,0 +1,111 @@
+#include <kapp.h>
+#include <qmenubar.h>
+#include <qmessagebox.h>
+#include <qpopupmenu.h>
+#include <qpushbutton.h>
+#include <qvbox.h>
+
+#include "qt-common.h"
+#include "qt-embedder.h"
+
+XEmbedQtEmbedder::XEmbedQtEmbedder ()
+{
+ // Create menu
+ QPopupMenu *file_menu = new QPopupMenu (this);
+
+ menuBar()->insertItem ("&File", file_menu);
+
+ file_menu->insertItem( "&Quit", this, SLOT( maybeQuit() ), CTRL+Key_Q );
+
+ vbox_ = new QVBox (this);
+
+ setCentralWidget (vbox_);
+
+ QPushButton *button;
+
+ button = new QPushButton ("Add Active GTK+ Child", vbox_);
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(addActiveGtkChild()));
+
+ button = new QPushButton ("Add Passive GTK+ Child", vbox_);
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(addPassiveGtkChild()));
+
+ button = new QPushButton ("Add Active Qt Child", vbox_);
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(addActiveQtChild()));
+
+ button = new QPushButton ("Add Passive Qt Child", vbox_);
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(addPassiveQtChild()));
+
+ button = new QPushButton ("Remove Last Child", vbox_);
+ QObject::connect (button, SIGNAL(clicked()), this, SLOT(removeChild()));
+}
+
+void
+XEmbedQtEmbedder::addChild (bool active, bool isQt)
+{
+ XEmbedQtChildSite *site = new XEmbedQtChildSite (vbox_, active, isQt);
+
+ embedders_.append (site);
+}
+
+void
+XEmbedQtEmbedder::addActiveGtkChild ()
+{
+ addChild (TRUE, FALSE);
+}
+
+void
+XEmbedQtEmbedder::addPassiveGtkChild ()
+{
+ addChild (FALSE, FALSE);
+}
+
+void
+XEmbedQtEmbedder::addActiveQtChild ()
+{
+ addChild (TRUE, TRUE);
+}
+
+void
+XEmbedQtEmbedder::addPassiveQtChild ()
+{
+ addChild (FALSE, TRUE);
+}
+
+void
+XEmbedQtEmbedder::removeChild ()
+{
+ if (!embedders_.isEmpty ())
+ {
+ embedders_.getLast()->close();
+ embedders_.removeLast();
+ }
+}
+
+void
+XEmbedQtEmbedder::maybeQuit ()
+{
+ QMessageBox mb( "qt-embedder", "Really Quit?",
+ QMessageBox::Information,
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::Cancel | QMessageBox::Escape,
+ 0, this );
+ mb.setButtonText( QMessageBox::Yes, "&Quit" );
+ mb.setButtonText( QMessageBox::No, "Cancel");
+
+ if (mb.exec() == QMessageBox::Yes)
+ {
+ qApp->closeAllWindows ();
+ }
+}
+
+int main( int argc, char **argv )
+{
+ KApplication a( argc, argv, "qt-embedder" );
+
+ XEmbedQtEmbedder *embedder = new XEmbedQtEmbedder ();
+
+ a.setMainWidget( embedder );
+ embedder->show();
+
+ return a.exec();
+}
diff --git a/xembed/tests/qt-embedder.h b/xembed/tests/qt-embedder.h
new file mode 100644
index 0000000..ab678f9
--- /dev/null
+++ b/xembed/tests/qt-embedder.h
@@ -0,0 +1,28 @@
+#include <qmainwindow.h>
+#include <qptrlist.h>
+
+class QVBox;
+
+class XEmbedQtEmbedder : public QMainWindow
+{
+ Q_OBJECT
+
+ public:
+
+ XEmbedQtEmbedder ();
+
+ private:
+ QVBox *vbox_;
+ QPtrList<QWidget> embedders_;
+
+ void addChild (bool active, bool isQt);
+
+ private slots:
+
+ void addActiveGtkChild ();
+ void addPassiveGtkChild ();
+ void addActiveQtChild ();
+ void addPassiveQtChild ();
+ void removeChild ();
+ void maybeQuit ();
+};