diff options
-rw-r--r-- | chrome/browser/printing/print_dialog_gtk.cc | 166 | ||||
-rw-r--r-- | chrome/browser/printing/print_dialog_gtk.h | 7 | ||||
-rw-r--r-- | printing/print_dialog_gtk_interface.h | 13 | ||||
-rw-r--r-- | printing/print_settings_initializer_gtk.cc | 13 | ||||
-rw-r--r-- | printing/printing_context_cairo.cc | 38 |
5 files changed, 200 insertions, 37 deletions
diff --git a/chrome/browser/printing/print_dialog_gtk.cc b/chrome/browser/printing/print_dialog_gtk.cc index 4f549db..72a7c4c 100644 --- a/chrome/browser/printing/print_dialog_gtk.cc +++ b/chrome/browser/printing/print_dialog_gtk.cc @@ -10,6 +10,9 @@ #include <sys/stat.h> #include <sys/types.h> +#include <string> +#include <vector> + #include "base/file_util.h" #include "base/file_util_proxy.h" #include "base/logging.h" @@ -18,8 +21,64 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" #include "printing/metafile.h" +#include "printing/print_job_constants.h" #include "printing/print_settings_initializer_gtk.h" +using printing::PageRanges; +using printing::PrintSettings; + +namespace { + +// Helper class to track GTK printers. +class GtkPrinterList { + public: + GtkPrinterList() : default_printer_(NULL) { + gtk_enumerate_printers((GtkPrinterFunc)SetPrinter, this, NULL, TRUE); + } + + ~GtkPrinterList() { + for (std::vector<GtkPrinter*>::iterator it = printers_.begin(); + it < printers_.end(); ++it) { + g_object_unref(*it); + } + } + + GtkPrinter* default_printer() { + return default_printer_; + } + + GtkPrinter* GetPrinterWithName(const char* name) { + if (!name || !*name) + return NULL; + + for (std::vector<GtkPrinter*>::iterator it = printers_.begin(); + it < printers_.end(); ++it) { + if (strcmp(name, gtk_printer_get_name(*it)) == 0) { + return *it; + } + } + + return NULL; + } + + private: + // Callback function used by gtk_enumerate_printers() to get all printer. + static bool SetPrinter(GtkPrinter* printer, GtkPrinterList* printer_list) { + if (gtk_printer_is_default(printer)) + printer_list->default_printer_ = printer; + + g_object_ref(printer); + printer_list->printers_.push_back(printer); + + return false; + } + + std::vector<GtkPrinter*> printers_; + GtkPrinter* default_printer_; +}; + +} // namespace + // static printing::PrintDialogGtkInterface* PrintDialogGtk::CreatePrintDialog( PrintingContextCairo* context) { @@ -34,17 +93,15 @@ PrintDialogGtk::PrintDialogGtk(PrintingContextCairo* context) gtk_settings_(NULL), page_setup_(NULL), printer_(NULL) { - GtkWindow* parent = BrowserList::GetLastActive()->window()->GetNativeHandle(); - - // TODO(estade): We need a window title here. - dialog_ = gtk_print_unix_dialog_new(NULL, parent); } PrintDialogGtk::~PrintDialogGtk() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - gtk_widget_destroy(dialog_); - dialog_ = NULL; + if (dialog_) { + gtk_widget_destroy(dialog_); + dialog_ = NULL; + } if (gtk_settings_) { g_object_unref(gtk_settings_); gtk_settings_ = NULL; @@ -59,12 +116,81 @@ PrintDialogGtk::~PrintDialogGtk() { } } +void PrintDialogGtk::UseDefaultSettings() { + DCHECK(!save_document_event_.get()); + DCHECK(!page_setup_); + + // |gtk_settings_| is a new object. + gtk_settings_ = gtk_print_settings_new(); + + scoped_ptr<GtkPrinterList> printer_list(new GtkPrinterList); + printer_ = printer_list->default_printer(); + if (printer_) { + g_object_ref(printer_); + gtk_print_settings_set_printer(gtk_settings_, + gtk_printer_get_name(printer_)); +#if GTK_CHECK_VERSION(2, 14, 0) + page_setup_ = gtk_printer_get_default_page_size(printer_); +#endif + } + + if (!page_setup_) + page_setup_ = gtk_page_setup_new(); + + // No page range to initialize for default settings. + PageRanges ranges_vector; + InitPrintSettings(ranges_vector); +} + +bool PrintDialogGtk::UpdateSettings(const DictionaryValue& settings, + const printing::PageRanges& ranges) { + std::string printer_name; + settings.GetString(printing::kSettingPrinterName, &printer_name); + + scoped_ptr<GtkPrinterList> printer_list(new GtkPrinterList); + printer_ = printer_list->GetPrinterWithName(printer_name.c_str()); + if (!printer_) + return false; + g_object_ref(printer_); + gtk_print_settings_set_printer(gtk_settings_, + gtk_printer_get_name(printer_)); + + bool landscape; + if (!settings.GetBoolean(printing::kSettingLandscape, &landscape)) + return false; + + gtk_print_settings_set_orientation( + gtk_settings_, + landscape ? GTK_PAGE_ORIENTATION_LANDSCAPE : + GTK_PAGE_ORIENTATION_PORTRAIT); + + int copies; + if (!settings.GetInteger(printing::kSettingCopies, &copies)) + return false; + gtk_print_settings_set_n_copies(gtk_settings_, copies); + + bool collate; + if (!settings.GetBoolean(printing::kSettingCollate, &collate)) + return false; + gtk_print_settings_set_collate(gtk_settings_, collate); + + // TODO(thestig) Color: gtk_print_settings_set_color() does not work. + // TODO(thestig) Duplex: gtk_print_settings_set_duplex() does not work. + + InitPrintSettings(ranges); + return true; +} + void PrintDialogGtk::ShowDialog( PrintingContextCairo::PrintSettingsCallback* callback) { DCHECK(!save_document_event_.get()); callback_ = callback; + GtkWindow* parent = BrowserList::GetLastActive()->window()->GetNativeHandle(); + // TODO(estade): We need a window title here. + dialog_ = gtk_print_unix_dialog_new(NULL, parent); + // Set modal so user cannot focus the same tab and press print again. gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE); @@ -120,17 +246,25 @@ void PrintDialogGtk::OnResponse(GtkWidget* dialog, int response_id) { switch (response_id) { case GTK_RESPONSE_OK: { + if (gtk_settings_) + g_object_unref(gtk_settings_); gtk_settings_ = gtk_print_unix_dialog_get_settings( GTK_PRINT_UNIX_DIALOG(dialog_)); + + if (printer_) + g_object_unref(printer_); printer_ = gtk_print_unix_dialog_get_selected_printer( GTK_PRINT_UNIX_DIALOG(dialog_)); g_object_ref(printer_); + + if (page_setup_) + g_object_unref(page_setup_); page_setup_ = gtk_print_unix_dialog_get_page_setup( GTK_PRINT_UNIX_DIALOG(dialog_)); g_object_ref(page_setup_); // Handle page ranges. - printing::PageRanges ranges_vector; + PageRanges ranges_vector; gint num_ranges; GtkPageRange* gtk_range = gtk_print_settings_get_page_ranges(gtk_settings_, &num_ranges); @@ -144,7 +278,7 @@ void PrintDialogGtk::OnResponse(GtkWidget* dialog, int response_id) { g_free(gtk_range); } - printing::PrintSettings settings; + PrintSettings settings; printing::PrintSettingsInitializerGtk::InitPrintSettings( gtk_settings_, page_setup_, ranges_vector, false, &settings); context_->InitWithSettings(settings); @@ -199,6 +333,15 @@ void PrintDialogGtk::SaveDocumentToDisk(const printing::Metafile* metafile, void PrintDialogGtk::SendDocumentToPrinter(const string16& document_name) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // If |printer_| is NULL then somehow the GTK printer list changed out under + // us. In which case, just bail out. + if (!printer_) { + // Matches AddRef() in PrintDocument(); + Release(); + return; + } + GtkPrintJob* print_job = gtk_print_job_new( UTF16ToUTF8(document_name).c_str(), printer_, @@ -228,3 +371,10 @@ void PrintDialogGtk::OnJobCompleted(GtkPrintJob* print_job, GError* error) { // Printing finished. Matches AddRef() in PrintDocument(); Release(); } + +void PrintDialogGtk::InitPrintSettings(const PageRanges& page_ranges) { + PrintSettings settings; + printing::PrintSettingsInitializerGtk::InitPrintSettings( + gtk_settings_, page_setup_, page_ranges, false, &settings); + context_->InitWithSettings(settings); +} diff --git a/chrome/browser/printing/print_dialog_gtk.h b/chrome/browser/printing/print_dialog_gtk.h index c6d999f..7ec804f 100644 --- a/chrome/browser/printing/print_dialog_gtk.h +++ b/chrome/browser/printing/print_dialog_gtk.h @@ -38,6 +38,9 @@ class PrintDialogGtk PrintingContextCairo* context); // printing::PrintDialogGtkInterface implementation. + virtual void UseDefaultSettings(); + virtual bool UpdateSettings(const DictionaryValue& settings, + const printing::PageRanges& ranges); virtual void ShowDialog( PrintingContextCairo::PrintSettingsCallback* callback); virtual void PrintDocument(const printing::Metafile* metafile, @@ -68,6 +71,10 @@ class PrintDialogGtk GError* error); void OnJobCompleted(GtkPrintJob* print_job, GError* error); + // Helper function for initializing |context_|'s PrintSettings with a given + // set of |page_ranges|. + void InitPrintSettings(const printing::PageRanges& page_ranges); + // Printing dialog callback. PrintingContextCairo::PrintSettingsCallback* callback_; PrintingContextCairo* context_; diff --git a/printing/print_dialog_gtk_interface.h b/printing/print_dialog_gtk_interface.h index dab0c9c..c47f978 100644 --- a/printing/print_dialog_gtk_interface.h +++ b/printing/print_dialog_gtk_interface.h @@ -17,7 +17,18 @@ class Metafile; // correct without exposing those requirements to printing/. class PrintDialogGtkInterface { public: - // Shows the dialog and handles the response with |callback|. + // Tell the dialog to use the default print setting. + virtual void UseDefaultSettings() = 0; + + // Update the dialog to use |settings| and |ranges|, where |settings| is a + // dictionary of settings with possible keys from + // printing/print_job_constants.h. Only used when printing without the system + // print dialog. E.g. for Print Preview. Returns false on error. + virtual bool UpdateSettings(const DictionaryValue& settings, + const PageRanges& ranges) = 0; + + // Shows the dialog and handles the response with |callback|. Only used when + // printing with the native print dialog. virtual void ShowDialog( PrintingContextCairo::PrintSettingsCallback* callback) = 0; diff --git a/printing/print_settings_initializer_gtk.cc b/printing/print_settings_initializer_gtk.cc index a42561ba..9b8915c 100644 --- a/printing/print_settings_initializer_gtk.cc +++ b/printing/print_settings_initializer_gtk.cc @@ -33,9 +33,6 @@ void PrintSettingsInitializerGtk::InitPrintSettings( print_settings->ranges = new_ranges; print_settings->selection_only = print_selection_only; - GtkPageOrientation orientation = gtk_print_settings_get_orientation(settings); - print_settings->set_landscape(orientation == GTK_PAGE_ORIENTATION_LANDSCAPE); - gfx::Size physical_size_device_units; gfx::Rect printable_area_device_units; int dpi = gtk_print_settings_get_resolution(settings); @@ -68,6 +65,16 @@ void PrintSettingsInitializerGtk::InitPrintSettings( print_settings->SetPrinterPrintableArea(physical_size_device_units, printable_area_device_units, dpi); + + // Note: With the normal GTK print dialog, when the user selects the landscape + // orientation, all that does is change the paper size. Which seems to be + // enough to render the right output and send it to the printer. + // The orientation value stays as portrait and does not actually affect + // printing. + // Thus this is only useful in print preview mode, where we manually set the + // orientation and change the paper size ourselves. + GtkPageOrientation orientation = gtk_print_settings_get_orientation(settings); + print_settings->SetOrientation(orientation == GTK_PAGE_ORIENTATION_LANDSCAPE); } const double PrintSettingsInitializerGtk::kTopMarginInInch = 0.25; diff --git a/printing/printing_context_cairo.cc b/printing/printing_context_cairo.cc index 6b24063..81d8696 100644 --- a/printing/printing_context_cairo.cc +++ b/printing/printing_context_cairo.cc @@ -8,11 +8,11 @@ #include "base/values.h" #include "printing/metafile.h" #include "printing/print_job_constants.h" -#include "printing/print_settings_initializer_gtk.h" #include "printing/units.h" #if defined(OS_CHROMEOS) #include <unicode/ulocdata.h> +#include "printing/print_settings_initializer_gtk.h" #else #include <gtk/gtk.h> #include <gtk/gtkprintunixdialog.h> @@ -78,8 +78,6 @@ void PrintingContextCairo::AskUserForSettings( #if defined(OS_CHROMEOS) callback->Run(OK); #else - print_dialog_ = create_dialog_func_(this); - print_dialog_->AddRefToDialog(); print_dialog_->ShowDialog(callback); #endif // defined(OS_CHROMEOS) } @@ -128,20 +126,12 @@ PrintingContext::Result PrintingContextCairo::UseDefaultSettings() { settings_.SetPrinterPrintableArea(physical_size_device_units, printable_area_device_units, dpi); -#else // defined(OS_CHROMEOS) - GtkWidget* dialog = gtk_print_unix_dialog_new(NULL, NULL); - GtkPrintSettings* settings = - gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog)); - GtkPageSetup* page_setup = - gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog)); - - PageRanges ranges_vector; // Nothing to initialize for default settings. - PrintSettingsInitializerGtk::InitPrintSettings( - settings, page_setup, ranges_vector, false, &settings_); - - g_object_unref(settings); - // |page_setup| is owned by dialog, so it does not need to be unref'ed. - gtk_widget_destroy(dialog); +#else + if (!print_dialog_) { + print_dialog_ = create_dialog_func_(this); + print_dialog_->AddRefToDialog(); + } + print_dialog_->UseDefaultSettings(); #endif // defined(OS_CHROMEOS) return OK; @@ -149,19 +139,17 @@ PrintingContext::Result PrintingContextCairo::UseDefaultSettings() { PrintingContext::Result PrintingContextCairo::UpdatePrintSettings( const DictionaryValue& job_settings, const PageRanges& ranges) { +#if defined(OS_CHROMEOS) + NOTIMPLEMENTED(); + return OK; +#else DCHECK(!in_print_job_); - bool landscape; - if (!job_settings.GetBoolean(kSettingLandscape, &landscape)) + if (!print_dialog_->UpdateSettings(job_settings, ranges)) return OnError(); - settings_.SetOrientation(landscape); - settings_.ranges = ranges; - - // TODO(kmadhusu): Update other print settings such as number of copies, - // collate, duplex printing, etc., - return OK; +#endif } PrintingContext::Result PrintingContextCairo::InitWithSettings( |