From 0a6848d70bd49d67034ceae005ce972386f08553 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 30 Apr 2020 18:45:01 +0100 Subject: [PATCH] Remove gtk_dialog_run() from GtkPrintUnixDialog Replace it with an explicit nested main loop, as we need to block the signal handler currently being emitted depending on the response of the overwrite confirmation dialog. This is a bit of a hack, and the only reason we need it is that the print dialog will load the last used path as the output file name, when printing to a file; this means that, in theory, it would be possible to press Print without selecting a file, and accidentally overwriting an existing file. It would be much simpler if we did not store the last used path, and always explicitly asked the user to select a file; this would avoid destructive actions, and would allow us to rely on the overwrite confirmation dialog right inside the file chooser. --- gtk/gtkprintunixdialog.c | 74 ++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/gtk/gtkprintunixdialog.c b/gtk/gtkprintunixdialog.c index eb9d008a04..6b9730f1a0 100644 --- a/gtk/gtkprintunixdialog.c +++ b/gtk/gtkprintunixdialog.c @@ -150,7 +150,7 @@ static void printer_status_cb (GtkPrintBackend *backend, GtkPrintUnixDialog *dialog); static void update_collate_icon (GtkToggleButton *toggle_button, GtkPrintUnixDialog *dialog); -static gboolean error_dialogs (GtkPrintUnixDialog *print_dialog, +static void error_dialogs (GtkPrintUnixDialog *print_dialog, gint print_dialog_response_id, gpointer data); static void emit_ok_response (GtkTreeView *tree_view, @@ -604,31 +604,42 @@ set_busy_cursor (GtkPrintUnixDialog *dialog, gtk_widget_set_cursor (widget, NULL); } +typedef struct { + GMainLoop *loop; + int response; +} ConfirmationData; + +static void +on_confirmation_dialog_response (GtkWidget *dialog, + int response, + gpointer user_data) +{ + ConfirmationData *data = user_data; + + data->response = response; + + g_main_loop_quit (data->loop); + + gtk_window_destroy (GTK_WINDOW (dialog)); +} + /* This function handles error messages before printing. */ -static gboolean +static void error_dialogs (GtkPrintUnixDialog *dialog, gint dialog_response_id, gpointer data) { - GtkPrinterOption *option = NULL; - GtkPrinter *printer = NULL; - GtkWindow *toplevel = NULL; - GFile *file = NULL; - gchar *basename = NULL; - gchar *dirname = NULL; - int response; - if (dialog != NULL && dialog_response_id == GTK_RESPONSE_OK) { - printer = gtk_print_unix_dialog_get_selected_printer (dialog); + GtkPrinter *printer = gtk_print_unix_dialog_get_selected_printer (dialog); if (printer != NULL) { if (dialog->request_details_tag || !gtk_printer_is_accepting_jobs (printer)) { g_signal_stop_emission_by_name (dialog, "response"); - return TRUE; + return; } /* Shows overwrite confirmation dialog in the case of printing @@ -636,18 +647,22 @@ error_dialogs (GtkPrintUnixDialog *dialog, */ if (gtk_printer_is_virtual (printer)) { - option = gtk_printer_option_set_lookup (dialog->options, - "gtk-main-page-custom-input"); + GtkPrinterOption *option = + gtk_printer_option_set_lookup (dialog->options, + "gtk-main-page-custom-input"); if (option != NULL && option->type == GTK_PRINTER_OPTION_TYPE_FILESAVE) { - file = g_file_new_for_uri (option->value); + GFile *file = g_file_new_for_uri (option->value); if (g_file_query_exists (file, NULL)) { - GFile *parent; GtkWidget *message_dialog; + GtkWindow *toplevel; + char *basename; + char *dirname; + GFile *parent; toplevel = get_toplevel (GTK_WIDGET (dialog)); @@ -682,19 +697,29 @@ error_dialogs (GtkPrintUnixDialog *dialog, gtk_window_group_add_window (gtk_window_get_group (toplevel), GTK_WINDOW (message_dialog)); - response = gtk_dialog_run (GTK_DIALOG (message_dialog)); + gtk_window_present (GTK_WINDOW (message_dialog)); - gtk_window_destroy (GTK_WINDOW (message_dialog)); + /* Block on the confirmation dialog until we have a response, + * so that we can stop the "response" signal emission on the + * print dialog + */ + ConfirmationData cdata; + + cdata.loop = g_main_loop_new (NULL, FALSE); + cdata.response = 0; + + g_signal_connect (message_dialog, "response", + G_CALLBACK (on_confirmation_dialog_response), + &cdata); + + g_main_loop_run (cdata.loop); + g_main_loop_unref (cdata.loop); g_free (dirname); g_free (basename); - if (response != GTK_RESPONSE_ACCEPT) - { - g_signal_stop_emission_by_name (dialog, "response"); - g_object_unref (file); - return TRUE; - } + if (cdata.response != GTK_RESPONSE_ACCEPT) + g_signal_stop_emission_by_name (dialog, "response"); } g_object_unref (file); @@ -702,7 +727,6 @@ error_dialogs (GtkPrintUnixDialog *dialog, } } } - return FALSE; } static void