| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/ui/libgtk2ui/print_dialog_gtk2.h" | |
| 6 | |
| 7 #include <gtk/gtkunixprint.h> | |
| 8 | |
| 9 #include <algorithm> | |
| 10 #include <cmath> | |
| 11 #include <string> | |
| 12 #include <vector> | |
| 13 | |
| 14 #include "base/bind.h" | |
| 15 #include "base/files/file_util.h" | |
| 16 #include "base/files/file_util_proxy.h" | |
| 17 #include "base/lazy_instance.h" | |
| 18 #include "base/logging.h" | |
| 19 #include "base/macros.h" | |
| 20 #include "base/strings/utf_string_conversions.h" | |
| 21 #include "base/values.h" | |
| 22 #include "chrome/browser/ui/libgtk2ui/gtk2_util.h" | |
| 23 #include "chrome/browser/ui/libgtk2ui/printing_gtk2_util.h" | |
| 24 #include "printing/metafile.h" | |
| 25 #include "printing/print_job_constants.h" | |
| 26 #include "printing/print_settings.h" | |
| 27 #include "ui/aura/window.h" | |
| 28 #include "ui/events/platform/x11/x11_event_source.h" | |
| 29 | |
| 30 using content::BrowserThread; | |
| 31 using printing::PageRanges; | |
| 32 using printing::PrintSettings; | |
| 33 | |
| 34 namespace { | |
| 35 | |
| 36 #if defined(USE_CUPS) | |
| 37 // CUPS Duplex attribute and values. | |
| 38 const char kCUPSDuplex[] = "cups-Duplex"; | |
| 39 const char kDuplexNone[] = "None"; | |
| 40 const char kDuplexTumble[] = "DuplexTumble"; | |
| 41 const char kDuplexNoTumble[] = "DuplexNoTumble"; | |
| 42 #endif | |
| 43 | |
| 44 int kPaperSizeTresholdMicrons = 100; | |
| 45 int kMicronsInMm = 1000; | |
| 46 | |
| 47 // Checks whether gtk_paper_size can be used to represent user selected media. | |
| 48 // In fuzzy match mode checks that paper sizes are "close enough" (less than | |
| 49 // 1mm difference). In the exact mode, looks for the paper with the same PPD | |
| 50 // name and "close enough" size. | |
| 51 bool PaperSizeMatch(GtkPaperSize* gtk_paper_size, | |
| 52 const PrintSettings::RequestedMedia& media, | |
| 53 bool fuzzy_match) { | |
| 54 if (!gtk_paper_size) { | |
| 55 return false; | |
| 56 } | |
| 57 gfx::Size paper_size_microns( | |
| 58 static_cast<int>(gtk_paper_size_get_width(gtk_paper_size, GTK_UNIT_MM) * | |
| 59 kMicronsInMm + 0.5), | |
| 60 static_cast<int>(gtk_paper_size_get_height(gtk_paper_size, GTK_UNIT_MM) * | |
| 61 kMicronsInMm + 0.5)); | |
| 62 int diff = std::max( | |
| 63 std::abs(paper_size_microns.width() - media.size_microns.width()), | |
| 64 std::abs(paper_size_microns.height() - media.size_microns.height())); | |
| 65 if (fuzzy_match) { | |
| 66 return diff <= kPaperSizeTresholdMicrons; | |
| 67 } | |
| 68 return !media.vendor_id.empty() && | |
| 69 media.vendor_id == gtk_paper_size_get_ppd_name(gtk_paper_size) && | |
| 70 diff <= kPaperSizeTresholdMicrons; | |
| 71 } | |
| 72 | |
| 73 // Looks up a paper size matching (in terms of PaperSizeMatch) the user selected | |
| 74 // media in the paper size list reported by GTK. Returns NULL if there's no | |
| 75 // match found. | |
| 76 GtkPaperSize* FindPaperSizeMatch(GList* gtk_paper_sizes, | |
| 77 const PrintSettings::RequestedMedia& media) { | |
| 78 GtkPaperSize* first_fuzzy_match = NULL; | |
| 79 for (GList* p = gtk_paper_sizes; p && p->data; p = g_list_next(p)) { | |
| 80 GtkPaperSize* gtk_paper_size = static_cast<GtkPaperSize*>(p->data); | |
| 81 if (PaperSizeMatch(gtk_paper_size, media, false)) { | |
| 82 return gtk_paper_size; | |
| 83 } | |
| 84 if (!first_fuzzy_match && PaperSizeMatch(gtk_paper_size, media, true)) { | |
| 85 first_fuzzy_match = gtk_paper_size; | |
| 86 } | |
| 87 } | |
| 88 return first_fuzzy_match; | |
| 89 } | |
| 90 | |
| 91 class StickyPrintSettingGtk { | |
| 92 public: | |
| 93 StickyPrintSettingGtk() : last_used_settings_(gtk_print_settings_new()) { | |
| 94 } | |
| 95 ~StickyPrintSettingGtk() { | |
| 96 NOTREACHED(); // Intended to be used with a Leaky LazyInstance. | |
| 97 } | |
| 98 | |
| 99 GtkPrintSettings* settings() { | |
| 100 return last_used_settings_; | |
| 101 } | |
| 102 | |
| 103 void SetLastUsedSettings(GtkPrintSettings* settings) { | |
| 104 DCHECK(last_used_settings_); | |
| 105 g_object_unref(last_used_settings_); | |
| 106 last_used_settings_ = gtk_print_settings_copy(settings); | |
| 107 } | |
| 108 | |
| 109 private: | |
| 110 GtkPrintSettings* last_used_settings_; | |
| 111 | |
| 112 DISALLOW_COPY_AND_ASSIGN(StickyPrintSettingGtk); | |
| 113 }; | |
| 114 | |
| 115 base::LazyInstance<StickyPrintSettingGtk>::Leaky g_last_used_settings = | |
| 116 LAZY_INSTANCE_INITIALIZER; | |
| 117 | |
| 118 // Helper class to track GTK printers. | |
| 119 class GtkPrinterList { | |
| 120 public: | |
| 121 GtkPrinterList() : default_printer_(NULL) { | |
| 122 gtk_enumerate_printers(SetPrinter, this, NULL, TRUE); | |
| 123 } | |
| 124 | |
| 125 ~GtkPrinterList() { | |
| 126 for (std::vector<GtkPrinter*>::iterator it = printers_.begin(); | |
| 127 it < printers_.end(); ++it) { | |
| 128 g_object_unref(*it); | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 // Can return NULL if there's no default printer. E.g. Printer on a laptop | |
| 133 // is "home_printer", but the laptop is at work. | |
| 134 GtkPrinter* default_printer() { | |
| 135 return default_printer_; | |
| 136 } | |
| 137 | |
| 138 // Can return NULL if the printer cannot be found due to: | |
| 139 // - Printer list out of sync with printer dialog UI. | |
| 140 // - Querying for non-existant printers like 'Print to PDF'. | |
| 141 GtkPrinter* GetPrinterWithName(const std::string& name) { | |
| 142 if (name.empty()) | |
| 143 return NULL; | |
| 144 | |
| 145 for (std::vector<GtkPrinter*>::iterator it = printers_.begin(); | |
| 146 it < printers_.end(); ++it) { | |
| 147 if (gtk_printer_get_name(*it) == name) { | |
| 148 return *it; | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 return NULL; | |
| 153 } | |
| 154 | |
| 155 private: | |
| 156 // Callback function used by gtk_enumerate_printers() to get all printer. | |
| 157 static gboolean SetPrinter(GtkPrinter* printer, gpointer data) { | |
| 158 GtkPrinterList* printer_list = reinterpret_cast<GtkPrinterList*>(data); | |
| 159 if (gtk_printer_is_default(printer)) | |
| 160 printer_list->default_printer_ = printer; | |
| 161 | |
| 162 g_object_ref(printer); | |
| 163 printer_list->printers_.push_back(printer); | |
| 164 | |
| 165 return FALSE; | |
| 166 } | |
| 167 | |
| 168 std::vector<GtkPrinter*> printers_; | |
| 169 GtkPrinter* default_printer_; | |
| 170 }; | |
| 171 | |
| 172 } // namespace | |
| 173 | |
| 174 // static | |
| 175 printing::PrintDialogGtkInterface* PrintDialogGtk2::CreatePrintDialog( | |
| 176 PrintingContextLinux* context) { | |
| 177 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 178 return new PrintDialogGtk2(context); | |
| 179 } | |
| 180 | |
| 181 PrintDialogGtk2::PrintDialogGtk2(PrintingContextLinux* context) | |
| 182 : context_(context), | |
| 183 dialog_(NULL), | |
| 184 gtk_settings_(NULL), | |
| 185 page_setup_(NULL), | |
| 186 printer_(NULL) { | |
| 187 } | |
| 188 | |
| 189 PrintDialogGtk2::~PrintDialogGtk2() { | |
| 190 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 191 | |
| 192 if (dialog_) { | |
| 193 aura::Window* parent = libgtk2ui::GetAuraTransientParent(dialog_); | |
| 194 if (parent) { | |
| 195 parent->RemoveObserver(this); | |
| 196 libgtk2ui::ClearAuraTransientParent(dialog_); | |
| 197 } | |
| 198 gtk_widget_destroy(dialog_); | |
| 199 dialog_ = NULL; | |
| 200 } | |
| 201 if (gtk_settings_) { | |
| 202 g_object_unref(gtk_settings_); | |
| 203 gtk_settings_ = NULL; | |
| 204 } | |
| 205 if (page_setup_) { | |
| 206 g_object_unref(page_setup_); | |
| 207 page_setup_ = NULL; | |
| 208 } | |
| 209 if (printer_) { | |
| 210 g_object_unref(printer_); | |
| 211 printer_ = NULL; | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 void PrintDialogGtk2::UseDefaultSettings() { | |
| 216 DCHECK(!page_setup_); | |
| 217 DCHECK(!printer_); | |
| 218 | |
| 219 // |gtk_settings_| is a new copy. | |
| 220 gtk_settings_ = | |
| 221 gtk_print_settings_copy(g_last_used_settings.Get().settings()); | |
| 222 page_setup_ = gtk_page_setup_new(); | |
| 223 | |
| 224 PrintSettings settings; | |
| 225 InitPrintSettings(&settings); | |
| 226 } | |
| 227 | |
| 228 bool PrintDialogGtk2::UpdateSettings(printing::PrintSettings* settings) { | |
| 229 if (!gtk_settings_) { | |
| 230 gtk_settings_ = | |
| 231 gtk_print_settings_copy(g_last_used_settings.Get().settings()); | |
| 232 } | |
| 233 | |
| 234 std::unique_ptr<GtkPrinterList> printer_list(new GtkPrinterList); | |
| 235 printer_ = printer_list->GetPrinterWithName( | |
| 236 base::UTF16ToUTF8(settings->device_name())); | |
| 237 if (printer_) { | |
| 238 g_object_ref(printer_); | |
| 239 gtk_print_settings_set_printer(gtk_settings_, | |
| 240 gtk_printer_get_name(printer_)); | |
| 241 if (!page_setup_) { | |
| 242 page_setup_ = gtk_printer_get_default_page_size(printer_); | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 gtk_print_settings_set_n_copies(gtk_settings_, settings->copies()); | |
| 247 gtk_print_settings_set_collate(gtk_settings_, settings->collate()); | |
| 248 | |
| 249 #if defined(USE_CUPS) | |
| 250 std::string color_value; | |
| 251 std::string color_setting_name; | |
| 252 printing::GetColorModelForMode(settings->color(), &color_setting_name, | |
| 253 &color_value); | |
| 254 gtk_print_settings_set(gtk_settings_, color_setting_name.c_str(), | |
| 255 color_value.c_str()); | |
| 256 | |
| 257 if (settings->duplex_mode() != printing::UNKNOWN_DUPLEX_MODE) { | |
| 258 const char* cups_duplex_mode = NULL; | |
| 259 switch (settings->duplex_mode()) { | |
| 260 case printing::LONG_EDGE: | |
| 261 cups_duplex_mode = kDuplexNoTumble; | |
| 262 break; | |
| 263 case printing::SHORT_EDGE: | |
| 264 cups_duplex_mode = kDuplexTumble; | |
| 265 break; | |
| 266 case printing::SIMPLEX: | |
| 267 cups_duplex_mode = kDuplexNone; | |
| 268 break; | |
| 269 default: // UNKNOWN_DUPLEX_MODE | |
| 270 NOTREACHED(); | |
| 271 break; | |
| 272 } | |
| 273 gtk_print_settings_set(gtk_settings_, kCUPSDuplex, cups_duplex_mode); | |
| 274 } | |
| 275 #endif | |
| 276 if (!page_setup_) | |
| 277 page_setup_ = gtk_page_setup_new(); | |
| 278 | |
| 279 if (page_setup_ && !settings->requested_media().IsDefault()) { | |
| 280 const PrintSettings::RequestedMedia& requested_media = | |
| 281 settings->requested_media(); | |
| 282 GtkPaperSize* gtk_current_paper_size = | |
| 283 gtk_page_setup_get_paper_size(page_setup_); | |
| 284 if (!PaperSizeMatch(gtk_current_paper_size, requested_media, | |
| 285 true /*fuzzy_match*/)) { | |
| 286 GList* gtk_paper_sizes = | |
| 287 gtk_paper_size_get_paper_sizes(false /*include_custom*/); | |
| 288 if (gtk_paper_sizes) { | |
| 289 GtkPaperSize* matching_gtk_paper_size = | |
| 290 FindPaperSizeMatch(gtk_paper_sizes, requested_media); | |
| 291 if (matching_gtk_paper_size) { | |
| 292 VLOG(1) << "Using listed paper size"; | |
| 293 gtk_page_setup_set_paper_size(page_setup_, matching_gtk_paper_size); | |
| 294 } else { | |
| 295 VLOG(1) << "Using custom paper size"; | |
| 296 GtkPaperSize* custom_size = gtk_paper_size_new_custom( | |
| 297 requested_media.vendor_id.c_str(), | |
| 298 requested_media.vendor_id.c_str(), | |
| 299 requested_media.size_microns.width() / kMicronsInMm, | |
| 300 requested_media.size_microns.height() / kMicronsInMm, | |
| 301 GTK_UNIT_MM); | |
| 302 gtk_page_setup_set_paper_size(page_setup_, custom_size); | |
| 303 gtk_paper_size_free(custom_size); | |
| 304 } | |
| 305 #if GTK_CHECK_VERSION(2,28,0) | |
| 306 g_list_free_full(gtk_paper_sizes, | |
| 307 reinterpret_cast<GDestroyNotify>(gtk_paper_size_free)); | |
| 308 #else | |
| 309 g_list_foreach(gtk_paper_sizes, | |
| 310 reinterpret_cast<GFunc>(gtk_paper_size_free), NULL); | |
| 311 g_list_free(gtk_paper_sizes); | |
| 312 #endif | |
| 313 } | |
| 314 } else { | |
| 315 VLOG(1) << "Using default paper size"; | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 gtk_print_settings_set_orientation( | |
| 320 gtk_settings_, | |
| 321 settings->landscape() ? GTK_PAGE_ORIENTATION_LANDSCAPE : | |
| 322 GTK_PAGE_ORIENTATION_PORTRAIT); | |
| 323 | |
| 324 InitPrintSettings(settings); | |
| 325 return true; | |
| 326 } | |
| 327 | |
| 328 void PrintDialogGtk2::ShowDialog( | |
| 329 gfx::NativeView parent_view, | |
| 330 bool has_selection, | |
| 331 const PrintingContextLinux::PrintSettingsCallback& callback) { | |
| 332 callback_ = callback; | |
| 333 DCHECK(!callback_.is_null()); | |
| 334 | |
| 335 dialog_ = gtk_print_unix_dialog_new(NULL, NULL); | |
| 336 libgtk2ui::SetGtkTransientForAura(dialog_, parent_view); | |
| 337 if (parent_view) | |
| 338 parent_view->AddObserver(this); | |
| 339 g_signal_connect(dialog_, "delete-event", | |
| 340 G_CALLBACK(gtk_widget_hide_on_delete), NULL); | |
| 341 | |
| 342 // Handle the case when the existing |gtk_settings_| has "selection" selected | |
| 343 // as the page range, but |has_selection| is false. | |
| 344 if (!has_selection) { | |
| 345 GtkPrintPages range = gtk_print_settings_get_print_pages(gtk_settings_); | |
| 346 if (range == GTK_PRINT_PAGES_SELECTION) | |
| 347 gtk_print_settings_set_print_pages(gtk_settings_, GTK_PRINT_PAGES_ALL); | |
| 348 } | |
| 349 | |
| 350 // Set modal so user cannot focus the same tab and press print again. | |
| 351 gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE); | |
| 352 | |
| 353 // Since we only generate PDF, only show printers that support PDF. | |
| 354 // TODO(thestig) Add more capabilities to support? | |
| 355 GtkPrintCapabilities cap = static_cast<GtkPrintCapabilities>( | |
| 356 GTK_PRINT_CAPABILITY_GENERATE_PDF | | |
| 357 GTK_PRINT_CAPABILITY_PAGE_SET | | |
| 358 GTK_PRINT_CAPABILITY_COPIES | | |
| 359 GTK_PRINT_CAPABILITY_COLLATE | | |
| 360 GTK_PRINT_CAPABILITY_REVERSE); | |
| 361 gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog_), | |
| 362 cap); | |
| 363 gtk_print_unix_dialog_set_embed_page_setup(GTK_PRINT_UNIX_DIALOG(dialog_), | |
| 364 TRUE); | |
| 365 gtk_print_unix_dialog_set_support_selection(GTK_PRINT_UNIX_DIALOG(dialog_), | |
| 366 TRUE); | |
| 367 gtk_print_unix_dialog_set_has_selection(GTK_PRINT_UNIX_DIALOG(dialog_), | |
| 368 has_selection); | |
| 369 gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog_), | |
| 370 gtk_settings_); | |
| 371 g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this); | |
| 372 gtk_widget_show(dialog_); | |
| 373 | |
| 374 // We need to call gtk_window_present after making the widgets visible to make | |
| 375 // sure window gets correctly raised and gets focus. | |
| 376 gtk_window_present_with_time( | |
| 377 GTK_WINDOW(dialog_), ui::X11EventSource::GetInstance()->GetTimestamp()); | |
| 378 } | |
| 379 | |
| 380 void PrintDialogGtk2::PrintDocument(const printing::MetafilePlayer& metafile, | |
| 381 const base::string16& document_name) { | |
| 382 // This runs on the print worker thread, does not block the UI thread. | |
| 383 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 384 | |
| 385 // The document printing tasks can outlive the PrintingContext that created | |
| 386 // this dialog. | |
| 387 AddRef(); | |
| 388 | |
| 389 bool success = base::CreateTemporaryFile(&path_to_pdf_); | |
| 390 | |
| 391 if (success) { | |
| 392 base::File file; | |
| 393 file.Initialize(path_to_pdf_, | |
| 394 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); | |
| 395 success = metafile.SaveTo(&file); | |
| 396 file.Close(); | |
| 397 if (!success) | |
| 398 base::DeleteFile(path_to_pdf_, false); | |
| 399 } | |
| 400 | |
| 401 if (!success) { | |
| 402 LOG(ERROR) << "Saving metafile failed"; | |
| 403 // Matches AddRef() above. | |
| 404 Release(); | |
| 405 return; | |
| 406 } | |
| 407 | |
| 408 // No errors, continue printing. | |
| 409 BrowserThread::PostTask( | |
| 410 BrowserThread::UI, | |
| 411 FROM_HERE, | |
| 412 base::Bind(&PrintDialogGtk2::SendDocumentToPrinter, this, document_name)); | |
| 413 } | |
| 414 | |
| 415 void PrintDialogGtk2::AddRefToDialog() { | |
| 416 AddRef(); | |
| 417 } | |
| 418 | |
| 419 void PrintDialogGtk2::ReleaseDialog() { | |
| 420 Release(); | |
| 421 } | |
| 422 | |
| 423 void PrintDialogGtk2::OnResponse(GtkWidget* dialog, int response_id) { | |
| 424 int num_matched_handlers = g_signal_handlers_disconnect_by_func( | |
| 425 dialog_, reinterpret_cast<gpointer>(&OnResponseThunk), this); | |
| 426 CHECK_EQ(1, num_matched_handlers); | |
| 427 | |
| 428 gtk_widget_hide(dialog_); | |
| 429 | |
| 430 switch (response_id) { | |
| 431 case GTK_RESPONSE_OK: { | |
| 432 if (gtk_settings_) | |
| 433 g_object_unref(gtk_settings_); | |
| 434 gtk_settings_ = gtk_print_unix_dialog_get_settings( | |
| 435 GTK_PRINT_UNIX_DIALOG(dialog_)); | |
| 436 | |
| 437 if (printer_) | |
| 438 g_object_unref(printer_); | |
| 439 printer_ = gtk_print_unix_dialog_get_selected_printer( | |
| 440 GTK_PRINT_UNIX_DIALOG(dialog_)); | |
| 441 g_object_ref(printer_); | |
| 442 | |
| 443 if (page_setup_) | |
| 444 g_object_unref(page_setup_); | |
| 445 page_setup_ = gtk_print_unix_dialog_get_page_setup( | |
| 446 GTK_PRINT_UNIX_DIALOG(dialog_)); | |
| 447 g_object_ref(page_setup_); | |
| 448 | |
| 449 // Handle page ranges. | |
| 450 PageRanges ranges_vector; | |
| 451 gint num_ranges; | |
| 452 bool print_selection_only = false; | |
| 453 switch (gtk_print_settings_get_print_pages(gtk_settings_)) { | |
| 454 case GTK_PRINT_PAGES_RANGES: { | |
| 455 GtkPageRange* gtk_range = | |
| 456 gtk_print_settings_get_page_ranges(gtk_settings_, &num_ranges); | |
| 457 if (gtk_range) { | |
| 458 for (int i = 0; i < num_ranges; ++i) { | |
| 459 printing::PageRange range; | |
| 460 range.from = gtk_range[i].start; | |
| 461 range.to = gtk_range[i].end; | |
| 462 ranges_vector.push_back(range); | |
| 463 } | |
| 464 g_free(gtk_range); | |
| 465 } | |
| 466 break; | |
| 467 } | |
| 468 case GTK_PRINT_PAGES_SELECTION: | |
| 469 print_selection_only = true; | |
| 470 break; | |
| 471 case GTK_PRINT_PAGES_ALL: | |
| 472 // Leave |ranges_vector| empty to indicate print all pages. | |
| 473 break; | |
| 474 case GTK_PRINT_PAGES_CURRENT: | |
| 475 default: | |
| 476 NOTREACHED(); | |
| 477 break; | |
| 478 } | |
| 479 | |
| 480 PrintSettings settings; | |
| 481 settings.set_ranges(ranges_vector); | |
| 482 settings.set_selection_only(print_selection_only); | |
| 483 InitPrintSettingsGtk(gtk_settings_, page_setup_, &settings); | |
| 484 context_->InitWithSettings(settings); | |
| 485 callback_.Run(PrintingContextLinux::OK); | |
| 486 callback_.Reset(); | |
| 487 return; | |
| 488 } | |
| 489 case GTK_RESPONSE_DELETE_EVENT: // Fall through. | |
| 490 case GTK_RESPONSE_CANCEL: { | |
| 491 callback_.Run(PrintingContextLinux::CANCEL); | |
| 492 callback_.Reset(); | |
| 493 return; | |
| 494 } | |
| 495 case GTK_RESPONSE_APPLY: | |
| 496 default: { | |
| 497 NOTREACHED(); | |
| 498 } | |
| 499 } | |
| 500 } | |
| 501 | |
| 502 | |
| 503 | |
| 504 static void OnJobCompletedThunk(GtkPrintJob* print_job, | |
| 505 gpointer user_data, | |
| 506 #if GTK_MAJOR_VERSION == 2 | |
| 507 GError* error | |
| 508 #else | |
| 509 const GError* error | |
| 510 #endif | |
| 511 ) { | |
| 512 static_cast<PrintDialogGtk2*>(user_data)->OnJobCompleted(print_job, error); | |
| 513 } | |
| 514 void PrintDialogGtk2::SendDocumentToPrinter( | |
| 515 const base::string16& document_name) { | |
| 516 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 517 | |
| 518 // If |printer_| is NULL then somehow the GTK printer list changed out under | |
| 519 // us. In which case, just bail out. | |
| 520 if (!printer_) { | |
| 521 // Matches AddRef() in PrintDocument(); | |
| 522 Release(); | |
| 523 return; | |
| 524 } | |
| 525 | |
| 526 // Save the settings for next time. | |
| 527 g_last_used_settings.Get().SetLastUsedSettings(gtk_settings_); | |
| 528 | |
| 529 GtkPrintJob* print_job = gtk_print_job_new( | |
| 530 base::UTF16ToUTF8(document_name).c_str(), | |
| 531 printer_, | |
| 532 gtk_settings_, | |
| 533 page_setup_); | |
| 534 gtk_print_job_set_source_file(print_job, path_to_pdf_.value().c_str(), NULL); | |
| 535 gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL); | |
| 536 } | |
| 537 | |
| 538 void PrintDialogGtk2::OnJobCompleted(GtkPrintJob* print_job, | |
| 539 const GError* error) { | |
| 540 if (error) | |
| 541 LOG(ERROR) << "Printing failed: " << error->message; | |
| 542 if (print_job) | |
| 543 g_object_unref(print_job); | |
| 544 base::FileUtilProxy::DeleteFile( | |
| 545 BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get(), | |
| 546 path_to_pdf_, false, base::FileUtilProxy::StatusCallback()); | |
| 547 // Printing finished. Matches AddRef() in PrintDocument(); | |
| 548 Release(); | |
| 549 } | |
| 550 | |
| 551 void PrintDialogGtk2::InitPrintSettings(PrintSettings* settings) { | |
| 552 InitPrintSettingsGtk(gtk_settings_, page_setup_, settings); | |
| 553 context_->InitWithSettings(*settings); | |
| 554 } | |
| 555 | |
| 556 void PrintDialogGtk2::OnWindowDestroying(aura::Window* window) { | |
| 557 DCHECK_EQ(libgtk2ui::GetAuraTransientParent(dialog_), window); | |
| 558 | |
| 559 libgtk2ui::ClearAuraTransientParent(dialog_); | |
| 560 window->RemoveObserver(this); | |
| 561 if (!callback_.is_null()) { | |
| 562 callback_.Run(PrintingContextLinux::CANCEL); | |
| 563 callback_.Reset(); | |
| 564 } | |
| 565 } | |
| OLD | NEW |