dialog iteration
- From: Havoc Pennington <hp redhat com>
- To: gtk-devel-list redhat com
- Subject: dialog iteration
- Date: 26 Mar 2000 14:15:43 -0500
Hi,
Another go based on Tim's ideas, please comment.
Notable features:
- set_transient_for virtualized in GtkWindow, so GtkDialog
can override it to destroy the dialog along with
the transient parent
- new GtkDialog is totally compatible with old GtkDialog
(except that it gets destroyed along with transient parent)
- I didn't support hide-instead-of-destroy-on-close because
this makes things a good bit harder to understand, in
my experience trying to explain GnomeDialog, and also
requires delete_event behavior inconsistent with GtkWindow.
If this is added I think the "close" signal should go in
GtkWindow to keep things consistent, and the "hide on close"
flag should be honored in gtkmain.c for delete_event
- I didn't support a "center over parent window" flag
because I don't think this should be programmer-configurable.
However GTK might do it automatically when the transient
parent is set.
Object arguments aren't implemented yet, I'll do that and also inline
docs once the design is final.
Patch appended, you may want to skip to "Index: gtkdialog.h" because
diff put the implementation first.
Havoc
Index: gtkdialog.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkdialog.c,v
retrieving revision 1.10
diff -u -u -r1.10 gtkdialog.c
--- gtkdialog.c 1999/02/24 07:34:16 1.10
+++ gtkdialog.c 2000/03/26 19:10:49
@@ -26,14 +26,41 @@
#include "gtkbutton.h"
#include "gtkdialog.h"
-#include "gtkhbox.h"
+#include "gtkhbbox.h"
#include "gtkhseparator.h"
#include "gtkvbox.h"
+#include "gtksignal.h"
-static void gtk_dialog_class_init (GtkDialogClass *klass);
-static void gtk_dialog_init (GtkDialog *dialog);
+static void gtk_dialog_class_init (GtkDialogClass *klass);
+static void gtk_dialog_init (GtkDialog *dialog);
+static void gtk_dialog_destroy (GtkObject *object);
+static void gtk_dialog_set_transient_for (GtkWindow *window,
+ GtkWindow *parent);
+
+static void gtk_dialog_parent_destroyed (GtkWindow *parent,
+ GtkDialog *dialog);
+
+static void action_area_add_handler (GtkWidget *action_area,
+ GtkWidget *child,
+ GtkDialog *dialog);
+
+static void action_area_remove_handler (GtkWidget *action_area,
+ GtkWidget *child,
+ GtkDialog *dialog);
+
+static void gtk_dialog_add_buttons_valist(GtkDialog *dialog,
+ const gchar *first_button_name,
+ gint first_action_id,
+ va_list args);
+
+enum {
+ ACTION,
+ LAST_SIGNAL
+};
+static GtkWindowClass *parent_class;
+static guint dialog_signals[LAST_SIGNAL];
GtkType
gtk_dialog_get_type (void)
@@ -63,6 +90,30 @@
static void
gtk_dialog_class_init (GtkDialogClass *class)
{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkWindowClass *window_class;
+
+ parent_class = gtk_type_class (gtk_window_get_type ());
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ window_class = (GtkWindowClass*) class;
+
+ dialog_signals[ACTION] =
+ gtk_signal_new ("action",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkDialogClass, action),
+ gtk_marshal_NONE__INT,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, dialog_signals, LAST_SIGNAL);
+
+ object_class->destroy = gtk_dialog_destroy;
+
+ window_class->set_transient_for = gtk_dialog_set_transient_for;
}
static void
@@ -74,7 +125,7 @@
gtk_container_add (GTK_CONTAINER (dialog), dialog->vbox);
gtk_widget_show (dialog->vbox);
- dialog->action_area = gtk_hbox_new (TRUE, 5);
+ dialog->action_area = gtk_hbutton_box_new ();
gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 10);
gtk_box_pack_end (GTK_BOX (dialog->vbox), dialog->action_area, FALSE, TRUE, 0);
gtk_widget_show (dialog->action_area);
@@ -82,10 +133,415 @@
separator = gtk_hseparator_new ();
gtk_box_pack_end (GTK_BOX (dialog->vbox), separator, FALSE, TRUE, 0);
gtk_widget_show (separator);
+
+
+ gtk_signal_connect_while_alive (GTK_OBJECT (dialog->action_area),
+ "add",
+ GTK_SIGNAL_FUNC (action_area_add_handler),
+ dialog,
+ GTK_OBJECT (dialog));
+
+ gtk_signal_connect_while_alive (GTK_OBJECT (dialog->action_area),
+ "remove",
+ GTK_SIGNAL_FUNC (action_area_remove_handler),
+ dialog,
+ GTK_OBJECT (dialog));
}
GtkWidget*
gtk_dialog_new (void)
{
return GTK_WIDGET (gtk_type_new (GTK_TYPE_DIALOG));
+}
+
+GtkWidget*
+gtk_dialog_new_empty (const gchar *title,
+ GtkWindow *parent,
+ GtkDialogFlags flags,
+ GtkWidget **zero_on_destroy)
+{
+ GtkWidget *widget;
+ GtkDialog *dialog;
+
+ widget = gtk_dialog_new ();
+
+ dialog = GTK_DIALOG (widget);
+
+ if (title != NULL)
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ if (parent != NULL)
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+ if (flags & GTK_DIALOG_MODAL)
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ if (flags & GTK_DIALOG_OUTLAST_PARENT)
+ gtk_dialog_set_outlast_parent (dialog, TRUE);
+
+ if (zero_on_destroy)
+ gtk_signal_connect (GTK_OBJECT (dialog),
+ "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ zero_on_destroy);
+
+ return widget;
+}
+
+GtkWidget*
+gtk_dialog_new_with_buttons (const gchar *title,
+ GtkWindow *parent,
+ GtkDialogFlags flags,
+ GtkWidget **zero_on_destroy,
+ const gchar *first_button_text,
+ gint first_action_id,
+ ...)
+{
+ GtkWidget *widget;
+ va_list args;
+
+ widget = gtk_dialog_new_empty (title, parent, flags, zero_on_destroy);
+
+ va_start (args, first_action_id);
+
+ gtk_dialog_add_buttons_valist (GTK_DIALOG (widget),
+ first_button_text, first_action_id,
+ args);
+
+ va_end (args);
+
+ return widget;
+}
+
+static void
+gtk_dialog_destroy (GtkObject *object)
+{
+ GtkDialog *dialog;
+
+ dialog = GTK_DIALOG (object);
+
+ if (dialog->parent_destroy_handler != 0)
+ {
+ gtk_signal_disconnect (GTK_OBJECT (GTK_WINDOW (dialog)->transient_parent),
+ dialog->parent_destroy_handler);
+
+ dialog->parent_destroy_handler = 0;
+ }
+}
+
+static void
+gtk_dialog_set_transient_for (GtkWindow *window,
+ GtkWindow *parent)
+{
+ GtkDialog *dialog;
+
+ dialog = GTK_DIALOG (window);
+
+ if (dialog->parent_destroy_handler != 0)
+ {
+ /* we are supposed to remove our handler if the
+ transient parent is destroyed. */
+ g_assert (window->transient_parent != NULL);
+ gtk_signal_disconnect (GTK_OBJECT (window->transient_parent),
+ dialog->parent_destroy_handler);
+
+ dialog->parent_destroy_handler = 0;
+ }
+
+ (* parent_class->set_transient_for) (window, parent);
+
+ g_assert (window->transient_parent == parent);
+
+ if (window->transient_parent != NULL)
+ {
+ dialog->parent_destroy_handler =
+ gtk_signal_connect (GTK_OBJECT (window->transient_parent),
+ "destroy",
+ GTK_SIGNAL_FUNC (gtk_dialog_parent_destroyed),
+ dialog);
+ }
+}
+
+static void
+gtk_dialog_parent_destroyed (GtkWindow *parent,
+ GtkDialog *dialog)
+{
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+ g_return_if_fail (dialog->parent_destroy_handler != 0);
+
+ /* The parent destroy handler will of course be destroyed
+ along with the parent. */
+ dialog->parent_destroy_handler = 0;
+
+ if (!dialog->outlast_parent)
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+void
+gtk_dialog_action (GtkDialog *dialog,
+ gint action_id)
+{
+ g_return_if_fail (dialog != NULL);
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ gtk_signal_emit (GTK_OBJECT (dialog),
+ dialog_signals[ACTION],
+ action_id);
+}
+
+void
+gtk_dialog_set_outlast_parent (GtkDialog *dialog,
+ gboolean setting)
+{
+ g_return_if_fail (dialog != NULL);
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ dialog->outlast_parent = setting != FALSE;
+}
+
+typedef struct {
+ gint action_id;
+ gboolean destroy_on_activate;
+} ActionData;
+
+static void
+action_widget_activated (GtkWidget *widget,
+ GtkDialog *dialog)
+{
+ ActionData *ad;
+ gint action_id;
+ gboolean destroy_on_activate;
+
+ g_return_if_fail (dialog != NULL);
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ action_id = GTK_ACTION_NONE;
+ destroy_on_activate = FALSE;
+
+ ad = gtk_object_get_data (GTK_OBJECT (widget),
+ "__gtk_dialog_action_data");
+
+ if (ad != NULL)
+ {
+ action_id = ad->action_id;
+ destroy_on_activate = ad->destroy_on_activate;
+ }
+
+ gtk_dialog_action (dialog, action_id);
+
+ if (destroy_on_activate)
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+action_area_add_handler (GtkWidget *action_area,
+ GtkWidget *child,
+ GtkDialog *dialog)
+{
+ g_return_if_fail (dialog != NULL);
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ if (GTK_WIDGET_CLASS (GTK_OBJECT (child)->klass)->activate_signal != 0)
+ {
+ const gchar* name =
+ gtk_signal_name (GTK_WIDGET_CLASS (GTK_OBJECT (child)->klass)->activate_signal != 0);
+
+ gtk_signal_connect_while_alive (GTK_OBJECT (child),
+ name,
+ GTK_SIGNAL_FUNC (action_widget_activated),
+ dialog,
+ GTK_OBJECT (dialog));
+ }
+ else
+ g_warning ("Only 'activatable' widgets can be packed into the action area of a GtkDialog");
+}
+
+static void
+action_area_remove_handler (GtkWidget *action_area,
+ GtkWidget *child,
+ GtkDialog *dialog)
+{
+ g_return_if_fail (dialog != NULL);
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+ gtk_signal_disconnect_by_func (GTK_OBJECT (action_area),
+ GTK_SIGNAL_FUNC (action_widget_activated),
+ dialog);
+
+ gtk_object_set_data (GTK_OBJECT (dialog),
+ "__gtk_dialog_action_data",
+ NULL);
+}
+
+void
+gtk_dialog_add_action_widget (GtkDialog *dialog,
+ GtkWidget *widget,
+ gint action_id,
+ gboolean destroy_on_activate)
+{
+ ActionData* ad;
+
+ g_return_if_fail (dialog != NULL);
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+ g_return_if_fail (widget != NULL);
+
+ ad = g_new (ActionData, 1);
+ ad->action_id = action_id;
+ ad->destroy_on_activate = destroy_on_activate;
+
+ gtk_object_set_data_full (GTK_OBJECT (widget),
+ "__gtk_dialog_action_data",
+ ad,
+ g_free);
+
+ gtk_box_pack_end (GTK_BOX (dialog->action_area),
+ widget,
+ FALSE, TRUE, 5);
+
+}
+
+void
+gtk_dialog_add_button (GtkDialog *dialog,
+ const gchar *button_text,
+ gint action_id)
+{
+ g_return_if_fail (dialog != NULL);
+ g_return_if_fail (GTK_IS_DIALOG (dialog));
+ g_return_if_fail (button_text != NULL);
+
+ /* FIXME when/if we have a stock icon/text facility, we want to
+ check whether button_text is a stock reference. */
+
+ gtk_dialog_add_action_widget (dialog,
+ gtk_button_new_with_label (button_text),
+ action_id,
+ TRUE);
+}
+
+static void
+gtk_dialog_add_buttons_valist(GtkDialog *dialog,
+ const gchar *first_button_text,
+ gint first_action_id,
+ va_list args)
+{
+ const gchar* text;
+ gint action_id;
+
+ text = first_button_text;
+ action_id = first_action_id;
+
+ while (text != NULL)
+ {
+ gtk_dialog_add_button (dialog, text, action_id);
+
+ text = va_arg (args, gchar*);
+ if (text == NULL)
+ break;
+ action_id = va_arg (args, int);
+ }
+}
+
+void
+gtk_dialog_add_buttons (GtkDialog *dialog,
+ const gchar *first_button_text,
+ gint first_action_id,
+ ...)
+{
+
+ va_list args;
+
+ va_start (args, first_action_id);
+
+ gtk_dialog_add_buttons_valist (dialog,
+ first_button_text, first_action_id,
+ args);
+
+ va_end (args);
+}
+
+typedef struct {
+ GtkDialog *dialog;
+ gint action_id;
+ GMainLoop *loop;
+ gint action_handler;
+ gint destroy_handler;
+} RunInfo;
+
+static void
+run_destroy_handler (GtkDialog *dialog, gpointer data)
+{
+ RunInfo *ri;
+
+ ri = data;
+
+ if (ri->loop != NULL)
+ {
+ g_main_quit (ri->loop);
+ g_main_destroy (ri->loop);
+ ri->loop = NULL;
+ }
+}
+
+static void
+run_action_handler (GtkDialog *dialog,
+ gint action_id,
+ gpointer data)
+{
+ RunInfo *ri;
+
+ ri = data;
+
+ ri->action_id = action_id;
+
+ g_main_quit (ri->loop);
+ g_main_destroy (ri->loop);
+ ri->loop = NULL;
+}
+
+gint
+gtk_dialog_run (GtkDialog *dialog)
+{
+ RunInfo ri = { NULL, GTK_ACTION_NONE, NULL, 0, 0 };
+ gboolean was_modal;
+
+ g_return_val_if_fail (dialog != NULL, -1);
+ g_return_val_if_fail (GTK_IS_DIALOG (dialog), -1);
+
+ gtk_object_ref (GTK_OBJECT (dialog));
+
+ was_modal = GTK_WINDOW (dialog)->modal;
+ if (!was_modal)
+ gtk_window_set_modal(GTK_WINDOW (dialog),TRUE);
+
+
+ ri.action_handler =
+ gtk_signal_connect (GTK_OBJECT (dialog),
+ "action",
+ GTK_SIGNAL_FUNC (run_action_handler),
+ &ri);
+
+ ri.destroy_handler =
+ gtk_signal_connect (GTK_OBJECT (dialog),
+ "destroy",
+ GTK_SIGNAL_FUNC (run_destroy_handler),
+ &ri);
+
+ ri.loop = g_main_new(FALSE);
+
+ g_main_run(ri.loop);
+
+ g_assert(ri.loop == NULL);
+
+ if (!GTK_OBJECT_DESTROYED (dialog))
+ {
+ if (!was_modal)
+ gtk_window_set_modal(GTK_WINDOW(dialog), FALSE);
+
+ gtk_signal_disconnect (GTK_OBJECT (dialog), ri.destroy_handler);
+ gtk_signal_disconnect (GTK_OBJECT (dialog), ri.action_handler);
+ }
+
+ gtk_object_unref (GTK_OBJECT (dialog));
+
+ return ri.action_id;
}
Index: gtkdialog.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkdialog.h,v
retrieving revision 1.6
diff -u -u -r1.6 gtkdialog.h
--- gtkdialog.h 2000/02/13 08:16:47 1.6
+++ gtkdialog.h 2000/03/26 19:10:49
@@ -36,6 +36,33 @@
extern "C" {
#endif /* __cplusplus */
+/* Parameters for dialog construction */
+typedef enum
+{
+ GTK_DIALOG_MODAL, /* call gtk_window_set_modal(win, TRUE) */
+ GTK_DIALOG_OUTLAST_PARENT /* don't destroy the dialog along with its
+ parent */
+} GtkDialogFlags;
+
+/* Convenience enum to use for action_id's. Positive values are
+ totally user-interpreted. GTK will sometimes return GTK_ACTION_NONE
+ if no action_id is available.
+
+ Typical usage is:
+ if (gtk_dialog_run(dialog) == GTK_ACTION_ACCEPT)
+ blah();
+
+*/
+typedef enum
+{
+ /* GTK returns this if an action widget has no action_id,
+ or the dialog gets destroyed with no action */
+ GTK_ACTION_NONE = 0,
+ /* GTK won't return these unless you pass them in
+ as the action for an action widget */
+ GTK_ACTION_REJECT = 1,
+ GTK_ACTION_ACCEPT = 2
+} GtkActionType;
#define GTK_TYPE_DIALOG (gtk_dialog_get_type ())
#define GTK_DIALOG(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_DIALOG, GtkDialog))
@@ -44,29 +71,70 @@
#define GTK_IS_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DIALOG))
#define GTK_DIALOG_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DIALOG, GtkDialogClass))
-
typedef struct _GtkDialog GtkDialog;
typedef struct _GtkDialogClass GtkDialogClass;
-typedef struct _GtkDialogButton GtkDialogButton;
-
struct _GtkDialog
{
GtkWindow window;
+ /*< public >*/
+
GtkWidget *vbox;
GtkWidget *action_area;
+
+ /*< private >*/
+ gboolean outlast_parent;
+ guint parent_destroy_handler;
};
struct _GtkDialogClass
{
GtkWindowClass parent_class;
+
+ void (* action) (GtkDialog *dialog, gint action_id);
};
GtkType gtk_dialog_get_type (void);
GtkWidget* gtk_dialog_new (void);
+GtkWidget* gtk_dialog_new_empty (const gchar *title,
+ GtkWindow *parent,
+ GtkDialogFlags flags,
+ GtkWidget **zero_on_destroy);
+GtkWidget* gtk_dialog_new_with_buttons (const gchar *title,
+ GtkWindow *parent,
+ GtkDialogFlags flags,
+ GtkWidget **zero_on_destroy,
+ const gchar *first_button_text,
+ gint first_action_id,
+ ...);
+
+void gtk_dialog_add_action_widget (GtkDialog *dialog,
+ GtkWidget *widget,
+ gint action_id,
+ gboolean destroy_on_activate);
+
+/* for these, destroy_on_activate defaults to TRUE */
+void gtk_dialog_add_button (GtkDialog *dialog,
+ const gchar *button_text,
+ gint action_id);
+
+void gtk_dialog_add_buttons (GtkDialog *dialog,
+ const gchar *first_button_text,
+ gint first_action_id,
+ ...);
+
+/* Emit action signal */
+void gtk_dialog_action (GtkDialog *dialog,
+ gint action_id);
+
+void gtk_dialog_set_outlast_parent (GtkDialog *dialog,
+ gboolean setting);
+
+/* Returns action_id */
+gint gtk_dialog_run (GtkDialog *dialog);
#ifdef __cplusplus
}
Index: gtkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.c,v
retrieving revision 1.79
diff -u -u -r1.79 gtkwindow.c
--- gtkwindow.c 1999/12/11 23:04:55 1.79
+++ gtkwindow.c 2000/03/26 19:10:54
@@ -49,6 +49,7 @@
enum {
SET_FOCUS,
+ SET_TRANSIENT_FOR,
LAST_SIGNAL
};
enum {
@@ -122,6 +123,8 @@
static void gtk_window_check_resize (GtkContainer *container);
static void gtk_window_real_set_focus (GtkWindow *window,
GtkWidget *focus);
+static void gtk_window_real_set_transient_for (GtkWindow *window,
+ GtkWindow *parent);
static void gtk_window_move_resize (GtkWindow *window);
static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a,
@@ -226,6 +229,15 @@
GTK_TYPE_NONE, 1,
GTK_TYPE_WIDGET);
+ window_signals[SET_TRANSIENT_FOR] =
+ gtk_signal_new ("set_transient_for",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkWindowClass, set_transient_for),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_WIDGET);
+
gtk_object_class_add_signals (object_class, window_signals, LAST_SIGNAL);
object_class->set_arg = gtk_window_set_arg;
@@ -256,6 +268,7 @@
container_class->check_resize = gtk_window_check_resize;
klass->set_focus = gtk_window_real_set_focus;
+ klass->set_transient_for = gtk_window_real_set_transient_for;
}
static void
@@ -702,38 +715,15 @@
gtk_window_set_transient_for (GtkWindow *window,
GtkWindow *parent)
{
- g_return_if_fail (window != 0);
-
- if (window->transient_parent)
- {
- if (GTK_WIDGET_REALIZED (window) &&
- GTK_WIDGET_REALIZED (window->transient_parent) &&
- (!parent || !GTK_WIDGET_REALIZED (parent)))
- gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
- GTK_WIDGET (window));
-
- gtk_window_unset_transient_for (window);
- }
-
- window->transient_parent = parent;
-
- if (parent)
- {
- gtk_signal_connect (GTK_OBJECT (parent), "destroy",
- GTK_SIGNAL_FUNC (gtk_widget_destroyed),
- &window->transient_parent);
- gtk_signal_connect (GTK_OBJECT (parent), "realize",
- GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
- window);
- gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
- GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
- window);
-
- if (GTK_WIDGET_REALIZED (window) &&
- GTK_WIDGET_REALIZED (parent))
- gtk_window_transient_parent_realized (GTK_WIDGET (parent),
- GTK_WIDGET (window));
- }
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (parent != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WINDOW (parent));
+ g_return_if_fail (window != parent);
+
+ gtk_signal_emit (GTK_OBJECT (window),
+ window_signals[SET_TRANSIENT_FOR],
+ parent);
}
static void
@@ -1512,6 +1502,48 @@
if (window->default_widget &&
(def_flags != GTK_WIDGET_FLAGS (window->default_widget)))
gtk_widget_queue_draw (window->default_widget);
+}
+
+static void
+gtk_window_real_set_transient_for (GtkWindow *window,
+ GtkWindow *parent)
+{
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (parent != NULL);
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WINDOW (parent));
+ g_return_if_fail (window != parent);
+
+ if (window->transient_parent)
+ {
+ if (GTK_WIDGET_REALIZED (window) &&
+ GTK_WIDGET_REALIZED (window->transient_parent) &&
+ (!parent || !GTK_WIDGET_REALIZED (parent)))
+ gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent),
+ GTK_WIDGET (window));
+
+ gtk_window_unset_transient_for (window);
+ }
+
+ window->transient_parent = parent;
+
+ if (parent)
+ {
+ gtk_signal_connect (GTK_OBJECT (parent), "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &window->transient_parent);
+ gtk_signal_connect (GTK_OBJECT (parent), "realize",
+ GTK_SIGNAL_FUNC (gtk_window_transient_parent_realized),
+ window);
+ gtk_signal_connect (GTK_OBJECT (parent), "unrealize",
+ GTK_SIGNAL_FUNC (gtk_window_transient_parent_unrealized),
+ window);
+
+ if (GTK_WIDGET_REALIZED (window) &&
+ GTK_WIDGET_REALIZED (parent))
+ gtk_window_transient_parent_realized (GTK_WIDGET (parent),
+ GTK_WIDGET (window));
+ }
}
/*********************************
Index: gtkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwindow.h,v
retrieving revision 1.20
diff -u -u -r1.20 gtkwindow.h
--- gtkwindow.h 2000/02/13 08:16:48 1.20
+++ gtkwindow.h 2000/03/26 19:10:54
@@ -86,6 +86,9 @@
void (* set_focus) (GtkWindow *window,
GtkWidget *focus);
+
+ void (* set_transient_for) (GtkWindow *window,
+ GtkWindow *parent);
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]