I have the following code that uses GTK+ widget toolkit to display a window with a button. Clicking this button will show a modal dialog. Note that the call to gtk_dialog_run
will recursively start another instance of the main loop, i.e. the on_click
function will not return until the dialog box is dismissed.
I would like to have two of these top-level windows, each with a button and the ability to spawn their own modal dialog. Showing the dialog would only disable the window that spawned it and there could be up to two active modal dialogs at the same time, one for each top-level window.
In win32, I could accomplish this simply by running each top-level window in a separate thread. However, it seems that gtk_main
can only be run from one thread. So how can I manage multiple window stacks in GTK+ (without sacrificing the simplicity of gtk_dialog_run
if possible)?
Update: The code now displays both windows and adds them to their respective window groups.
#include <gtk/gtk.h>
struct modal_stack
{
GtkWindowGroup * group;
GtkWidget * window;
};
static void on_click(GtkWidget *widget, gpointer sptr)
{
modal_stack * s = (modal_stack *)sptr;
GtkWidget * dialog = gtk_file_chooser_dialog_new(
"Open File", 0, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(s->window));
gtk_window_group_add_window(s->group, GTK_WINDOW(dialog));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_window_group_remove_window(s->group, GTK_WINDOW(dialog));
gtk_widget_destroy(dialog);
}
void create_window(modal_stack & s)
{
s.group = gtk_window_group_new();
s.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize(s.window, 200, 200);
g_signal_connect(G_OBJECT (s.window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT (s.window), "delete_event",
G_CALLBACK(gtk_main_quit), NULL);
GtkWidget * button = gtk_button_new ();
gtk_button_set_label(GTK_BUTTON(button), "show dialog");
g_signal_connect(G_OBJECT (button), "clicked",
G_CALLBACK(on_click), (gpointer) &s);
gtk_widget_show(button);
gtk_container_add(GTK_CONTAINER (s.window), button);
gtk_widget_show(s.window);
gtk_window_group_add_window(s.group, GTK_WINDOW(s.window));
}
int main(int argc, char *argv[])
{
gtk_init (&argc, &argv);
modal_stack wnd1, wnd2;
create_window(wnd1);
create_window(wnd2);
gtk_main();
}