the following is tiny example to show that its possible to use XEMBED
or just native X Window IDs to create host-managed plugin GUIs. GTK+2
and Qt3 both support XEMBED; GTK+2 supports use of native X Window ids
when creating new top level windows, i am not sure about Qt (does
anybody here know how to do it).
this means that a GTK host can manage a Qt GUI or vice versa, without
any toolkit specific hacks in the host or in a library linked by the
host.
i offer this as a proof of concept. i believe that our problems with
GUIs for plugins are pretty much over, modulo defining some standards
as per another recent from me.
--p
----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
gboolean
button_pressed (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
fprintf (stderr, "host: button press at %g,%g\n", event->x, event->y);
return TRUE;
}
gboolean
delete_event (GtkWidget* widget,
GdkEvent* event,
gpointer user_data)
{
fprintf (stderr, "host: window delete event\n");
gtk_main_quit ();
return TRUE;
}
gboolean
plugin_button_pressed (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data)
{
fprintf (stderr, "plug: button press at %g,%g\n", event->x, event->y);
return TRUE;
}
gboolean
plugin_delete_event (GtkWidget* widget,
GdkEvent* event,
gpointer user_data)
{
fprintf (stderr, "plug: window delete event\n");
gtk_main_quit ();
return FALSE;
}
int
plugin_main (GdkNativeWindow window_id)
{
GtkWidget* embedded_parent;
GtkWidget* dummy_label;
GdkWindow* foreign_window;
int argc = 1;
char **argv = (char **) malloc (sizeof (char*));
argv[0] = "plugin";
gtk_init (&argc, &argv);
#ifdef USE_XEMBED
embedded_parent = gtk_plug_new (window_id);
#else
embedded_parent = gtk_window_new (GTK_WINDOW_TOPLEVEL);
foreign_window = gdk_window_foreign_new (window_id);
gtk_widget_set_parent_window (embedded_parent, foreign_window);
#endif
dummy_label = gtk_label_new ("This is a LADSPA Plugin GUI");
gtk_container_add (GTK_CONTAINER(embedded_parent),
dummy_label);
gtk_signal_connect (GTK_OBJECT(embedded_parent),
"button-press-event",
GTK_SIGNAL_FUNC (plugin_button_pressed),
NULL);
gtk_signal_connect (GTK_OBJECT(embedded_parent),
"delete-event",
GTK_SIGNAL_FUNC (plugin_delete_event),
NULL);
gtk_widget_add_events (GTK_WIDGET (embedded_parent),
GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
gtk_widget_show (embedded_parent);
gtk_widget_show (dummy_label);
}
int
main (int argc, char *argv[])
{
gtk_init (&argc, &argv);
GtkWidget* embedded_parent;
GtkWidget* embedded_window;
embedded_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
#ifdef USE_XEMBED
embedded_parent = gtk_socket_new ();
gtk_container_add (GTK_CONTAINER(embedded_window),
embedded_parent);
gtk_widget_show (embedded_parent);
#endif
gtk_signal_connect (GTK_OBJECT(embedded_window),
"button-press-event",
GTK_SIGNAL_FUNC (button_pressed),
NULL);
gtk_signal_connect (GTK_OBJECT(embedded_window),
"delete-event",
GTK_SIGNAL_FUNC (delete_event),
NULL);
gtk_widget_add_events (GTK_WIDGET (embedded_window),
GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
gtk_widget_set_size_request (GTK_WIDGET(embedded_window), 100, 100);
gtk_window_set_title (GTK_WINDOW(embedded_window), "A Plugin");
gtk_widget_show (embedded_window);
gtk_widget_realize (embedded_window);
#ifdef USE_XEMBED
plugin_main (gtk_socket_get_id (GTK_SOCKET(embedded_parent)));
#else
plugin_main (GDK_WINDOW_XID (embedded_window->window));
#endif
gtk_main ();
}