mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-13 04:10:13 +00:00
Remove gtk_dialog_run()
Nested main loops are bad, as they introduce layers of complexity caused by the potential re-entrancy in the case of multiple event sources, like IPC, threads, etc. Additionally, the programming model they provide—stop the world while spinning a new loop—does not conform to the event-driven model employed by GTK.
This commit is contained in:
parent
0a6848d70b
commit
d54b7dec94
@ -678,7 +678,6 @@ GtkDialogFlags
|
||||
GtkResponseType
|
||||
gtk_dialog_new
|
||||
gtk_dialog_new_with_buttons
|
||||
gtk_dialog_run
|
||||
gtk_dialog_response
|
||||
gtk_dialog_add_button
|
||||
gtk_dialog_add_buttons
|
||||
|
172
gtk/gtkdialog.c
172
gtk/gtkdialog.c
@ -83,12 +83,6 @@
|
||||
* a dialog receives a delete event, the #GtkDialog::response signal will
|
||||
* be emitted with a response ID of #GTK_RESPONSE_DELETE_EVENT.
|
||||
*
|
||||
* If you want to block waiting for a dialog to return before returning
|
||||
* control flow to your code, you can call gtk_dialog_run(). This function
|
||||
* enters a recursive main loop and waits for the user to respond to the
|
||||
* dialog, returning the response ID corresponding to the button the user
|
||||
* clicked.
|
||||
*
|
||||
* For the simple dialog in the following example, in reality you’d probably
|
||||
* use #GtkMessageDialog to save yourself some effort. But you’d need to
|
||||
* create the dialog contents manually if you had more than a simple message
|
||||
@ -592,7 +586,6 @@ gtk_dialog_buildable_interface_init (GtkBuildableIface *iface)
|
||||
static gboolean
|
||||
gtk_dialog_close_request (GtkWindow *window)
|
||||
{
|
||||
/* emit response signal, this will shut down the loop if we are in gtk_dialog_run */
|
||||
gtk_dialog_response (GTK_DIALOG (window), GTK_RESPONSE_DELETE_EVENT);
|
||||
|
||||
return GTK_WINDOW_CLASS (gtk_dialog_parent_class)->close_request (window);
|
||||
@ -1011,9 +1004,8 @@ gtk_dialog_set_default_response (GtkDialog *dialog,
|
||||
* @response_id: response ID
|
||||
*
|
||||
* Emits the #GtkDialog::response signal with the given response ID.
|
||||
* Used to indicate that the user has responded to the dialog in some way;
|
||||
* typically either you or gtk_dialog_run() will be monitoring the
|
||||
* ::response signal and take appropriate action.
|
||||
*
|
||||
* Used to indicate that the user has responded to the dialog in some way.
|
||||
**/
|
||||
void
|
||||
gtk_dialog_response (GtkDialog *dialog,
|
||||
@ -1027,166 +1019,6 @@ gtk_dialog_response (GtkDialog *dialog,
|
||||
response_id);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkDialog *dialog;
|
||||
gint response_id;
|
||||
GMainLoop *loop;
|
||||
gboolean destroyed;
|
||||
} RunInfo;
|
||||
|
||||
static void
|
||||
shutdown_loop (RunInfo *ri)
|
||||
{
|
||||
if (g_main_loop_is_running (ri->loop))
|
||||
g_main_loop_quit (ri->loop);
|
||||
}
|
||||
|
||||
static void
|
||||
run_unmap_handler (GtkDialog *dialog, gpointer data)
|
||||
{
|
||||
RunInfo *ri = data;
|
||||
|
||||
shutdown_loop (ri);
|
||||
}
|
||||
|
||||
static void
|
||||
run_response_handler (GtkDialog *dialog,
|
||||
gint response_id,
|
||||
gpointer data)
|
||||
{
|
||||
RunInfo *ri;
|
||||
|
||||
ri = data;
|
||||
|
||||
ri->response_id = response_id;
|
||||
|
||||
shutdown_loop (ri);
|
||||
}
|
||||
|
||||
static void
|
||||
run_destroy_handler (GtkDialog *dialog, gpointer data)
|
||||
{
|
||||
RunInfo *ri = data;
|
||||
|
||||
/* shutdown_loop will be called by run_unmap_handler */
|
||||
|
||||
ri->destroyed = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_dialog_run:
|
||||
* @dialog: a #GtkDialog
|
||||
*
|
||||
* Blocks in a recursive main loop until the @dialog either emits the
|
||||
* #GtkDialog::response signal, or is destroyed. If the dialog is
|
||||
* destroyed during the call to gtk_dialog_run(), gtk_dialog_run() returns
|
||||
* #GTK_RESPONSE_NONE. Otherwise, it returns the response ID from the
|
||||
* ::response signal emission.
|
||||
*
|
||||
* Before entering the recursive main loop, gtk_dialog_run() calls
|
||||
* gtk_widget_show() on the dialog for you. Note that you still
|
||||
* need to show any children of the dialog yourself.
|
||||
*
|
||||
* During gtk_dialog_run(), the default behavior of delete events
|
||||
* is disabled; if the dialog receives a delete event, it will not be
|
||||
* destroyed as windows usually are, and gtk_dialog_run() will return
|
||||
* #GTK_RESPONSE_DELETE_EVENT. Also, during gtk_dialog_run() the dialog
|
||||
* will be modal. You can force gtk_dialog_run() to return at any time by
|
||||
* calling gtk_dialog_response() to emit the ::response signal. Destroying
|
||||
* the dialog during gtk_dialog_run() is a very bad idea, because your
|
||||
* post-run code won’t know whether the dialog was destroyed or not.
|
||||
*
|
||||
* After gtk_dialog_run() returns, you are responsible for hiding or
|
||||
* destroying the dialog if you wish to do so.
|
||||
*
|
||||
* Typical usage of this function might be:
|
||||
* |[<!-- language="C" -->
|
||||
* GtkWidget *dialog = gtk_dialog_new ();
|
||||
* // Set up dialog...
|
||||
*
|
||||
* int result = gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
* switch (result)
|
||||
* {
|
||||
* case GTK_RESPONSE_ACCEPT:
|
||||
* // do_application_specific_something ();
|
||||
* break;
|
||||
* default:
|
||||
* // do_nothing_since_dialog_was_cancelled ();
|
||||
* break;
|
||||
* }
|
||||
* gtk_window_destroy (dialog);
|
||||
* ]|
|
||||
*
|
||||
* Note that even though the recursive main loop gives the effect of a
|
||||
* modal dialog (it prevents the user from interacting with other
|
||||
* windows in the same window group while the dialog is run), callbacks
|
||||
* such as timeouts, IO channel watches, DND drops, etc, will
|
||||
* be triggered during a gtk_dialog_run() call.
|
||||
*
|
||||
* Returns: response ID
|
||||
**/
|
||||
gint
|
||||
gtk_dialog_run (GtkDialog *dialog)
|
||||
{
|
||||
RunInfo ri = { NULL, GTK_RESPONSE_NONE, NULL, FALSE };
|
||||
gboolean was_modal;
|
||||
gboolean was_hide_on_close;
|
||||
gulong response_handler;
|
||||
gulong unmap_handler;
|
||||
gulong destroy_handler;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_DIALOG (dialog), -1);
|
||||
|
||||
g_object_ref (dialog);
|
||||
|
||||
was_modal = gtk_window_get_modal (GTK_WINDOW (dialog));
|
||||
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
|
||||
was_hide_on_close = gtk_window_get_hide_on_close (GTK_WINDOW (dialog));
|
||||
gtk_window_set_hide_on_close (GTK_WINDOW (dialog), TRUE);
|
||||
|
||||
if (!gtk_widget_get_visible (GTK_WIDGET (dialog)))
|
||||
gtk_widget_show (GTK_WIDGET (dialog));
|
||||
|
||||
response_handler =
|
||||
g_signal_connect (dialog,
|
||||
"response",
|
||||
G_CALLBACK (run_response_handler),
|
||||
&ri);
|
||||
|
||||
unmap_handler =
|
||||
g_signal_connect (dialog,
|
||||
"unmap",
|
||||
G_CALLBACK (run_unmap_handler),
|
||||
&ri);
|
||||
|
||||
destroy_handler =
|
||||
g_signal_connect (dialog,
|
||||
"destroy",
|
||||
G_CALLBACK (run_destroy_handler),
|
||||
&ri);
|
||||
|
||||
ri.loop = g_main_loop_new (NULL, FALSE);
|
||||
g_main_loop_run (ri.loop);
|
||||
g_main_loop_unref (ri.loop);
|
||||
|
||||
ri.loop = NULL;
|
||||
|
||||
if (!ri.destroyed)
|
||||
{
|
||||
gtk_window_set_modal (GTK_WINDOW (dialog), was_modal);
|
||||
gtk_window_set_hide_on_close (GTK_WINDOW (dialog), was_hide_on_close);
|
||||
|
||||
g_signal_handler_disconnect (dialog, response_handler);
|
||||
g_signal_handler_disconnect (dialog, unmap_handler);
|
||||
g_signal_handler_disconnect (dialog, destroy_handler);
|
||||
}
|
||||
|
||||
g_object_unref (dialog);
|
||||
|
||||
return ri.response_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_dialog_get_widget_for_response:
|
||||
* @dialog: a #GtkDialog
|
||||
|
@ -176,10 +176,6 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gtk_dialog_response (GtkDialog *dialog,
|
||||
gint response_id);
|
||||
|
||||
/* Returns response_id */
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gint gtk_dialog_run (GtkDialog *dialog);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_dialog_get_content_area (GtkDialog *dialog);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
Loading…
Reference in New Issue
Block a user