From f00d46c83e04355baecdc8c19a37acef63ae6b3c Mon Sep 17 00:00:00 2001 From: "dholbert@cs.stanford.edu" Date: Wed, 30 Apr 2008 23:43:04 -0700 Subject: [PATCH] Bug 431190: Make Linux print dialog & page setup dialog modal. r+sr=vlad a=damons --- .../unixshared/nsPrintingPromptService.cpp | 4 +- widget/public/nsIPrintDialogService.h | 14 +-- widget/src/gtk2/Makefile.in | 1 + widget/src/gtk2/nsFilePicker.cpp | 2 + widget/src/gtk2/nsPrintDialogGTK.cpp | 89 +++++++++++++++++-- widget/src/gtk2/nsPrintDialogGTK.h | 5 +- widget/src/xpwidgets/nsBaseFilePicker.cpp | 2 + 7 files changed, 101 insertions(+), 16 deletions(-) diff --git a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp index 6df7bc59fc10..1a9f221b85bc 100644 --- a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp +++ b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp @@ -114,7 +114,7 @@ nsPrintingPromptService::ShowPrintDialog(nsIDOMWindow *parent, nsIWebBrowserPrin nsCOMPtr dlgPrint(do_GetService( NS_PRINTDIALOGSERVICE_CONTRACTID)); if (dlgPrint) - return dlgPrint->Show(printSettings); + return dlgPrint->Show(parent, printSettings); // Show the built-in dialog instead ParamBlock block; @@ -189,7 +189,7 @@ nsPrintingPromptService::ShowPageSetup(nsIDOMWindow *parent, nsIPrintSettings *p nsCOMPtr dlgPrint(do_GetService( NS_PRINTDIALOGSERVICE_CONTRACTID)); if (dlgPrint) - return dlgPrint->ShowPageSetup(printSettings); + return dlgPrint->ShowPageSetup(parent, printSettings); ParamBlock block; nsresult rv = block.Init(); diff --git a/widget/public/nsIPrintDialogService.h b/widget/public/nsIPrintDialogService.h index 1b8d5c5db4ff..bbebb8f55213 100644 --- a/widget/public/nsIPrintDialogService.h +++ b/widget/public/nsIPrintDialogService.h @@ -40,6 +40,7 @@ #include "nsISupports.h" +class nsIDOMWindow; class nsIPrintSettings; /* @@ -67,6 +68,7 @@ public: /** * Show the print dialog. + * @param aParent A DOM window the dialog will be parented to. * @param aSettings On entry, this contains initial settings for the * print dialog. On return, if the print operation should * proceed then this contains settings for the print @@ -75,17 +77,19 @@ public: * @return NS_ERROR_ABORT if the user indicated not to proceed * @return a suitable error for failures to show the print dialog. */ - NS_IMETHOD Show(nsIPrintSettings *aSettings) = 0; + NS_IMETHOD Show(nsIDOMWindow *aParent, nsIPrintSettings *aSettings) = 0; /** - * Show the page setup dialog. Note that there is no way to tell whether the user clicked OK or Cancel on the - * dialog. + * Show the page setup dialog. Note that there is no way to tell whether the + * user clicked OK or Cancel on the dialog. + * @param aParent A DOM window the dialog will be parented to. * @param aSettings On entry, this contains initial settings for the - * page setup dialog. On return, this contains new default page setup options. + * page setup dialog. On return, this contains new default + * page setup options. * @return NS_OK if everything is OK. * @return a suitable error for failures to show the page setup dialog. */ - NS_IMETHOD ShowPageSetup(nsIPrintSettings *aSettings) = 0; + NS_IMETHOD ShowPageSetup(nsIDOMWindow *aParent, nsIPrintSettings *aSettings) = 0; }; diff --git a/widget/src/gtk2/Makefile.in b/widget/src/gtk2/Makefile.in index 2d0620675674..6ae2d2810ba0 100644 --- a/widget/src/gtk2/Makefile.in +++ b/widget/src/gtk2/Makefile.in @@ -59,6 +59,7 @@ REQUIRES = xpcom \ gfx \ pref \ dom \ + docshell \ necko \ uconv \ intl \ diff --git a/widget/src/gtk2/nsFilePicker.cpp b/widget/src/gtk2/nsFilePicker.cpp index 53b9adaa0ccb..1118ecb96cb7 100644 --- a/widget/src/gtk2/nsFilePicker.cpp +++ b/widget/src/gtk2/nsFilePicker.cpp @@ -138,6 +138,8 @@ DECL_FUNC_PTR(gtk_image_new); DECL_FUNC_PTR(gtk_misc_set_padding); DECL_FUNC_PTR(gtk_file_chooser_set_local_only); +// XXXdholbert -- this function is duplicated in nsPrintDialogGTK.cpp +// and needs to be unified in some generic utility class. static GtkWindow * get_gtk_window_for_nsiwidget(nsIWidget *widget) { diff --git a/widget/src/gtk2/nsPrintDialogGTK.cpp b/widget/src/gtk2/nsPrintDialogGTK.cpp index 3111d6e99563..d31957cc0e1c 100644 --- a/widget/src/gtk2/nsPrintDialogGTK.cpp +++ b/widget/src/gtk2/nsPrintDialogGTK.cpp @@ -52,11 +52,77 @@ #include "nsNetUtil.h" #include "nsIStringBundle.h" #include "nsIPrintSettingsService.h" +#include "nsIDOMWindow.h" +#include "nsPIDOMWindow.h" +#include "nsIBaseWindow.h" +#include "nsIDocShellTreeItem.h" +#include "nsIDocShell.h" static const char header_footer_tags[][4] = {"", "&T", "&U", "&D", "&P", "&PT"}; #define CUSTOM_VALUE_INDEX NS_ARRAY_LENGTH(header_footer_tags) +// XXXdholbert Duplicated from widget/src/xpwidgets/nsBaseFilePicker.cpp +// Needs to be unified in some generic utility class. +static nsIWidget * +DOMWindowToWidget(nsIDOMWindow *dw) +{ + nsCOMPtr widget; + + nsCOMPtr window = do_QueryInterface(dw); + if (window) { + nsCOMPtr baseWin(do_QueryInterface(window->GetDocShell())); + + while (!widget && baseWin) { + baseWin->GetParentWidget(getter_AddRefs(widget)); + if (!widget) { + nsCOMPtr docShellAsItem(do_QueryInterface(baseWin)); + if (!docShellAsItem) + return nsnull; + + nsCOMPtr parent; + docShellAsItem->GetSameTypeParent(getter_AddRefs(parent)); + + window = do_GetInterface(parent); + if (!window) + return nsnull; + + baseWin = do_QueryInterface(window->GetDocShell()); + } + } + } + + // This will return a pointer that we're about to release, but + // that's ok since the docshell (nsIBaseWindow) holds the widget + // alive. + return widget.get(); +} + +// XXXdholbert Duplicated from widget/src/gtk2/nsFilePicker.cpp +// Needs to be unified in some generic utility class. +static GtkWindow * +get_gtk_window_for_nsiwidget(nsIWidget *widget) +{ + // Get native GdkWindow + GdkWindow *gdk_win = GDK_WINDOW(widget->GetNativeData(NS_NATIVE_WIDGET)); + if (!gdk_win) + return NULL; + + // Get the container + gpointer user_data = NULL; + gdk_window_get_user_data(gdk_win, &user_data); + if (!user_data) + return NULL; + + // Make sure its really a container + MozContainer *parent_container = MOZ_CONTAINER(user_data); + if (!parent_container) + return NULL; + + // Get its toplevel + return GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(parent_container))); +} + static void ShowCustomDialog(GtkComboBox *changed_box, gpointer user_data) { @@ -120,7 +186,7 @@ ShowCustomDialog(GtkComboBox *changed_box, gpointer user_data) class nsPrintDialogWidgetGTK { public: - nsPrintDialogWidgetGTK(nsIPrintSettings *aPrintSettings); + nsPrintDialogWidgetGTK(nsIDOMWindow *aParent, nsIPrintSettings *aPrintSettings); ~nsPrintDialogWidgetGTK() { gtk_widget_destroy(dialog); } NS_ConvertUTF16toUTF8 GetUTF8FromBundle(const char* aKey); const gint Run(); @@ -154,12 +220,15 @@ class nsPrintDialogWidgetGTK { void ExportHeaderFooter(nsIPrintSettings *aNS); }; -nsPrintDialogWidgetGTK::nsPrintDialogWidgetGTK(nsIPrintSettings *aSettings) +nsPrintDialogWidgetGTK::nsPrintDialogWidgetGTK(nsIDOMWindow *aParent, nsIPrintSettings *aSettings) { + GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(DOMWindowToWidget(aParent)); + NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal."); + nsCOMPtr bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); bundleSvc->CreateBundle("chrome://global/locale/gnomeprintdialog.properties", getter_AddRefs(printBundle)); - dialog = gtk_print_unix_dialog_new(GetUTF8FromBundle("printTitle").get(), NULL); + dialog = gtk_print_unix_dialog_new(GetUTF8FromBundle("printTitle").get(), gtkParent); gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog), GtkPrintCapabilities( @@ -495,11 +564,12 @@ nsPrintDialogServiceGTK::Init() } NS_IMETHODIMP -nsPrintDialogServiceGTK::Show(nsIPrintSettings *aSettings) +nsPrintDialogServiceGTK::Show(nsIDOMWindow *aParent, nsIPrintSettings *aSettings) { + NS_PRECONDITION(aParent, "aParent must not be null"); NS_PRECONDITION(aSettings, "aSettings must not be null"); - nsPrintDialogWidgetGTK printDialog(aSettings); + nsPrintDialogWidgetGTK printDialog(aParent, aSettings); nsresult rv = printDialog.ImportSettings(aSettings); NS_ENSURE_SUCCESS(rv, rv); @@ -528,11 +598,16 @@ nsPrintDialogServiceGTK::Show(nsIPrintSettings *aSettings) } NS_IMETHODIMP -nsPrintDialogServiceGTK::ShowPageSetup(nsIPrintSettings *aNSSettings) +nsPrintDialogServiceGTK::ShowPageSetup(nsIDOMWindow *aParent, + nsIPrintSettings *aNSSettings) { + NS_PRECONDITION(aParent, "aParent must not be null"); NS_PRECONDITION(aNSSettings, "aSettings must not be null"); NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); + GtkWindow* gtkParent = get_gtk_window_for_nsiwidget(DOMWindowToWidget(aParent)); + NS_ASSERTION(gtkParent, "Need a GTK window for dialog to be modal."); + nsCOMPtr aNSSettingsGTK(do_QueryInterface(aNSSettings)); if (!aNSSettingsGTK) return NS_ERROR_FAILURE; @@ -552,7 +627,7 @@ nsPrintDialogServiceGTK::ShowPageSetup(nsIPrintSettings *aNSSettings) GtkPrintSettings* gtkSettings = aNSSettingsGTK->GetGtkPrintSettings(); GtkPageSetup* oldPageSetup = aNSSettingsGTK->GetGtkPageSetup(); - GtkPageSetup* newPageSetup = gtk_print_run_page_setup_dialog(NULL, oldPageSetup, gtkSettings); + GtkPageSetup* newPageSetup = gtk_print_run_page_setup_dialog(gtkParent, oldPageSetup, gtkSettings); aNSSettingsGTK->SetGtkPageSetup(newPageSetup); diff --git a/widget/src/gtk2/nsPrintDialogGTK.h b/widget/src/gtk2/nsPrintDialogGTK.h index 1c2ec22a00b0..aa7c3fe2fc65 100644 --- a/widget/src/gtk2/nsPrintDialogGTK.h +++ b/widget/src/gtk2/nsPrintDialogGTK.h @@ -51,8 +51,9 @@ public: NS_DECL_ISUPPORTS NS_IMETHODIMP Init(); - NS_IMETHODIMP Show(nsIPrintSettings *aSettings); - NS_IMETHODIMP ShowPageSetup(nsIPrintSettings *aSettings); + NS_IMETHODIMP Show(nsIDOMWindow *aParent, nsIPrintSettings *aSettings); + NS_IMETHODIMP ShowPageSetup(nsIDOMWindow *aParent, + nsIPrintSettings *aSettings); }; #endif diff --git a/widget/src/xpwidgets/nsBaseFilePicker.cpp b/widget/src/xpwidgets/nsBaseFilePicker.cpp index 2cd3bc2b4af4..4dcf6fd4d537 100644 --- a/widget/src/xpwidgets/nsBaseFilePicker.cpp +++ b/widget/src/xpwidgets/nsBaseFilePicker.cpp @@ -69,6 +69,8 @@ nsBaseFilePicker::~nsBaseFilePicker() } +// XXXdholbert -- this function is duplicated in nsPrintDialogGTK.cpp +// and needs to be unified in some generic utility class. nsIWidget *nsBaseFilePicker::DOMWindowToWidget(nsIDOMWindow *dw) { nsCOMPtr widget;