1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include <gtk/gtkunixprint.h>
10 #include "mozilla/ArrayUtils.h"
12 #include "mozcontainer.h"
13 #include "nsIPrintSettings.h"
14 #include "nsIWidget.h"
15 #include "nsPrintDialogGTK.h"
16 #include "nsPrintSettingsGTK.h"
18 #include "nsReadableUtils.h"
20 #include "nsIStringBundle.h"
21 #include "nsIPrintSettingsService.h"
22 #include "nsIDOMWindow.h"
23 #include "nsPIDOMWindow.h"
24 #include "nsIBaseWindow.h"
25 #include "nsIDocShellTreeItem.h"
26 #include "nsIDocShell.h"
27 #include "WidgetUtils.h"
29 using namespace mozilla
;
30 using namespace mozilla::widget
;
32 static const char header_footer_tags
[][4] = {"", "&T", "&U", "&D", "&P", "&PT"};
34 #define CUSTOM_VALUE_INDEX gint(ArrayLength(header_footer_tags))
37 get_gtk_window_for_nsiwidget(nsIWidget
*widget
)
39 return GTK_WINDOW(widget
->GetNativeData(NS_NATIVE_SHELLWIDGET
));
43 ShowCustomDialog(GtkComboBox
*changed_box
, gpointer user_data
)
45 if (gtk_combo_box_get_active(changed_box
) != CUSTOM_VALUE_INDEX
) {
46 g_object_set_data(G_OBJECT(changed_box
), "previous-active", GINT_TO_POINTER(gtk_combo_box_get_active(changed_box
)));
50 GtkWindow
* printDialog
= GTK_WINDOW(user_data
);
51 nsCOMPtr
<nsIStringBundleService
> bundleSvc
=
52 do_GetService(NS_STRINGBUNDLE_CONTRACTID
);
54 nsCOMPtr
<nsIStringBundle
> printBundle
;
55 bundleSvc
->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle
));
56 nsAutoString intlString
;
58 printBundle
->GetStringFromName("headerFooterCustom", intlString
);
59 GtkWidget
* prompt_dialog
= gtk_dialog_new_with_buttons(NS_ConvertUTF16toUTF8(intlString
).get(), printDialog
,
60 (GtkDialogFlags
)(GTK_DIALOG_MODAL
),
61 GTK_STOCK_CANCEL
, GTK_RESPONSE_REJECT
,
62 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
64 gtk_dialog_set_default_response(GTK_DIALOG(prompt_dialog
), GTK_RESPONSE_ACCEPT
);
65 gtk_dialog_set_alternative_button_order(GTK_DIALOG(prompt_dialog
),
70 printBundle
->GetStringFromName("customHeaderFooterPrompt", intlString
);
71 GtkWidget
* custom_label
= gtk_label_new(NS_ConvertUTF16toUTF8(intlString
).get());
72 GtkWidget
* custom_entry
= gtk_entry_new();
73 GtkWidget
* question_icon
= gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION
, GTK_ICON_SIZE_DIALOG
);
75 // To be convenient, prefill the textbox with the existing value, if any, and select it all so they can easily
76 // both edit it and type in a new one.
77 const char* current_text
= (const char*) g_object_get_data(G_OBJECT(changed_box
), "custom-text");
79 gtk_entry_set_text(GTK_ENTRY(custom_entry
), current_text
);
80 gtk_editable_select_region(GTK_EDITABLE(custom_entry
), 0, -1);
82 gtk_entry_set_activates_default(GTK_ENTRY(custom_entry
), TRUE
);
84 GtkWidget
* custom_vbox
= gtk_vbox_new(TRUE
, 2);
85 gtk_box_pack_start(GTK_BOX(custom_vbox
), custom_label
, FALSE
, FALSE
, 0);
86 gtk_box_pack_start(GTK_BOX(custom_vbox
), custom_entry
, FALSE
, FALSE
, 5); // Make entry 5px underneath label
87 GtkWidget
* custom_hbox
= gtk_hbox_new(FALSE
, 2);
88 gtk_box_pack_start(GTK_BOX(custom_hbox
), question_icon
, FALSE
, FALSE
, 0);
89 gtk_box_pack_start(GTK_BOX(custom_hbox
), custom_vbox
, FALSE
, FALSE
, 10); // Make question icon 10px away from content
90 gtk_container_set_border_width(GTK_CONTAINER(custom_hbox
), 2);
91 gtk_widget_show_all(custom_hbox
);
93 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(prompt_dialog
))),
94 custom_hbox
, FALSE
, FALSE
, 0);
95 gint diag_response
= gtk_dialog_run(GTK_DIALOG(prompt_dialog
));
97 if (diag_response
== GTK_RESPONSE_ACCEPT
) {
98 const gchar
* response_text
= gtk_entry_get_text(GTK_ENTRY(custom_entry
));
99 g_object_set_data_full(G_OBJECT(changed_box
), "custom-text", strdup(response_text
), (GDestroyNotify
) free
);
100 g_object_set_data(G_OBJECT(changed_box
), "previous-active", GINT_TO_POINTER(CUSTOM_VALUE_INDEX
));
102 // Go back to the previous index
103 gint previous_active
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(changed_box
), "previous-active"));
104 gtk_combo_box_set_active(changed_box
, previous_active
);
107 gtk_widget_destroy(prompt_dialog
);
110 class nsPrintDialogWidgetGTK
{
112 nsPrintDialogWidgetGTK(nsPIDOMWindowOuter
*aParent
,
113 nsIPrintSettings
*aPrintSettings
);
114 ~nsPrintDialogWidgetGTK() { gtk_widget_destroy(dialog
); }
115 NS_ConvertUTF16toUTF8
GetUTF8FromBundle(const char* aKey
);
118 nsresult
ImportSettings(nsIPrintSettings
*aNSSettings
);
119 nsresult
ExportSettings(nsIPrintSettings
*aNSSettings
);
123 GtkWidget
* radio_as_laid_out
;
124 GtkWidget
* radio_selected_frame
;
125 GtkWidget
* radio_separate_frames
;
126 GtkWidget
* shrink_to_fit_toggle
;
127 GtkWidget
* print_bg_colors_toggle
;
128 GtkWidget
* print_bg_images_toggle
;
129 GtkWidget
* selection_only_toggle
;
130 GtkWidget
* header_dropdown
[3]; // {left, center, right}
131 GtkWidget
* footer_dropdown
[3];
133 nsCOMPtr
<nsIStringBundle
> printBundle
;
135 bool useNativeSelection
;
137 GtkWidget
* ConstructHeaderFooterDropdown(const char16_t
*currentString
);
138 const char* OptionWidgetToString(GtkWidget
*dropdown
);
140 /* Code to copy between GTK and NS print settings structures.
142 * "Import" means to copy from NS to GTK
143 * "Export" means to copy from GTK to NS
145 void ExportFramePrinting(nsIPrintSettings
*aNS
, GtkPrintSettings
*aSettings
);
146 void ExportHeaderFooter(nsIPrintSettings
*aNS
);
149 nsPrintDialogWidgetGTK::nsPrintDialogWidgetGTK(nsPIDOMWindowOuter
*aParent
,
150 nsIPrintSettings
*aSettings
)
152 nsCOMPtr
<nsIWidget
> widget
= WidgetUtils::DOMWindowToWidget(aParent
);
153 NS_ASSERTION(widget
, "Need a widget for dialog to be modal.");
154 GtkWindow
* gtkParent
= get_gtk_window_for_nsiwidget(widget
);
155 NS_ASSERTION(gtkParent
, "Need a GTK window for dialog to be modal.");
157 nsCOMPtr
<nsIStringBundleService
> bundleSvc
= do_GetService(NS_STRINGBUNDLE_CONTRACTID
);
158 bundleSvc
->CreateBundle("chrome://global/locale/printdialog.properties", getter_AddRefs(printBundle
));
160 dialog
= gtk_print_unix_dialog_new(GetUTF8FromBundle("printTitleGTK").get(), gtkParent
);
162 gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog
),
163 GtkPrintCapabilities(
164 GTK_PRINT_CAPABILITY_PAGE_SET
165 | GTK_PRINT_CAPABILITY_COPIES
166 | GTK_PRINT_CAPABILITY_COLLATE
167 | GTK_PRINT_CAPABILITY_REVERSE
168 | GTK_PRINT_CAPABILITY_SCALE
169 | GTK_PRINT_CAPABILITY_GENERATE_PDF
173 // The vast majority of magic numbers in this widget construction are padding. e.g. for
174 // the set_border_width below, 12px matches that of just about every other window.
175 GtkWidget
* custom_options_tab
= gtk_vbox_new(FALSE
, 0);
176 gtk_container_set_border_width(GTK_CONTAINER(custom_options_tab
), 12);
177 GtkWidget
* tab_label
= gtk_label_new(GetUTF8FromBundle("optionsTabLabelGTK").get());
180 aSettings
->GetHowToEnableFrameUI(&frameUIFlag
);
181 radio_as_laid_out
= gtk_radio_button_new_with_mnemonic(nullptr, GetUTF8FromBundle("asLaidOut").get());
182 if (frameUIFlag
== nsIPrintSettings::kFrameEnableNone
)
183 gtk_widget_set_sensitive(radio_as_laid_out
, FALSE
);
185 radio_selected_frame
= gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out
),
186 GetUTF8FromBundle("selectedFrame").get());
187 if (frameUIFlag
== nsIPrintSettings::kFrameEnableNone
||
188 frameUIFlag
== nsIPrintSettings::kFrameEnableAsIsAndEach
)
189 gtk_widget_set_sensitive(radio_selected_frame
, FALSE
);
191 radio_separate_frames
= gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out
),
192 GetUTF8FromBundle("separateFrames").get());
193 if (frameUIFlag
== nsIPrintSettings::kFrameEnableNone
)
194 gtk_widget_set_sensitive(radio_separate_frames
, FALSE
);
196 // "Print Frames" options label, bold and center-aligned
197 GtkWidget
* print_frames_label
= gtk_label_new(nullptr);
198 char* pangoMarkup
= g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("printFramesTitleGTK").get());
199 gtk_label_set_markup(GTK_LABEL(print_frames_label
), pangoMarkup
);
201 gtk_misc_set_alignment(GTK_MISC(print_frames_label
), 0, 0);
203 // Align the radio buttons slightly so they appear to fall under the aforementioned label as per the GNOME HIG
204 GtkWidget
* frames_radio_container
= gtk_alignment_new(0, 0, 0, 0);
205 gtk_alignment_set_padding(GTK_ALIGNMENT(frames_radio_container
), 8, 0, 12, 0);
207 // Radio buttons for the print frames options
208 GtkWidget
* frames_radio_list
= gtk_vbox_new(TRUE
, 2);
209 gtk_box_pack_start(GTK_BOX(frames_radio_list
), radio_as_laid_out
, FALSE
, FALSE
, 0);
210 gtk_box_pack_start(GTK_BOX(frames_radio_list
), radio_selected_frame
, FALSE
, FALSE
, 0);
211 gtk_box_pack_start(GTK_BOX(frames_radio_list
), radio_separate_frames
, FALSE
, FALSE
, 0);
212 gtk_container_add(GTK_CONTAINER(frames_radio_container
), frames_radio_list
);
214 // Check buttons for shrink-to-fit and print selection
215 GtkWidget
* check_buttons_container
= gtk_vbox_new(TRUE
, 2);
216 shrink_to_fit_toggle
= gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("shrinkToFit").get());
217 gtk_box_pack_start(GTK_BOX(check_buttons_container
), shrink_to_fit_toggle
, FALSE
, FALSE
, 0);
219 // GTK+2.18 and above allow us to add a "Selection" option to the main settings screen,
220 // rather than adding an option on a custom tab like we must do on older versions.
222 aSettings
->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB
, &canSelectText
);
223 if (gtk_major_version
> 2 ||
224 (gtk_major_version
== 2 && gtk_minor_version
>= 18)) {
225 useNativeSelection
= true;
227 "support-selection", TRUE
,
228 "has-selection", canSelectText
,
229 "embed-page-setup", TRUE
,
232 useNativeSelection
= false;
233 selection_only_toggle
= gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("selectionOnly").get());
234 gtk_widget_set_sensitive(selection_only_toggle
, canSelectText
);
235 gtk_box_pack_start(GTK_BOX(check_buttons_container
), selection_only_toggle
, FALSE
, FALSE
, 0);
238 // Check buttons for printing background
239 GtkWidget
* appearance_buttons_container
= gtk_vbox_new(TRUE
, 2);
240 print_bg_colors_toggle
= gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGColors").get());
241 print_bg_images_toggle
= gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGImages").get());
242 gtk_box_pack_start(GTK_BOX(appearance_buttons_container
), print_bg_colors_toggle
, FALSE
, FALSE
, 0);
243 gtk_box_pack_start(GTK_BOX(appearance_buttons_container
), print_bg_images_toggle
, FALSE
, FALSE
, 0);
245 // "Appearance" options label, bold and center-aligned
246 GtkWidget
* appearance_label
= gtk_label_new(nullptr);
247 pangoMarkup
= g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("printBGOptions").get());
248 gtk_label_set_markup(GTK_LABEL(appearance_label
), pangoMarkup
);
250 gtk_misc_set_alignment(GTK_MISC(appearance_label
), 0, 0);
252 GtkWidget
* appearance_container
= gtk_alignment_new(0, 0, 0, 0);
253 gtk_alignment_set_padding(GTK_ALIGNMENT(appearance_container
), 8, 0, 12, 0);
254 gtk_container_add(GTK_CONTAINER(appearance_container
), appearance_buttons_container
);
256 GtkWidget
* appearance_vertical_squasher
= gtk_vbox_new(FALSE
, 0);
257 gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher
), appearance_label
, FALSE
, FALSE
, 0);
258 gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher
), appearance_container
, FALSE
, FALSE
, 0);
260 // "Header & Footer" options label, bold and center-aligned
261 GtkWidget
* header_footer_label
= gtk_label_new(nullptr);
262 pangoMarkup
= g_markup_printf_escaped("<b>%s</b>", GetUTF8FromBundle("headerFooter").get());
263 gtk_label_set_markup(GTK_LABEL(header_footer_label
), pangoMarkup
);
265 gtk_misc_set_alignment(GTK_MISC(header_footer_label
), 0, 0);
267 GtkWidget
* header_footer_container
= gtk_alignment_new(0, 0, 0, 0);
268 gtk_alignment_set_padding(GTK_ALIGNMENT(header_footer_container
), 8, 0, 12, 0);
271 // --- Table for making the header and footer options ---
272 GtkWidget
* header_footer_table
= gtk_table_new(3, 3, FALSE
); // 3x3 table
273 nsString header_footer_str
[3];
275 aSettings
->GetHeaderStrLeft(header_footer_str
[0]);
276 aSettings
->GetHeaderStrCenter(header_footer_str
[1]);
277 aSettings
->GetHeaderStrRight(header_footer_str
[2]);
279 for (unsigned int i
= 0; i
< ArrayLength(header_dropdown
); i
++) {
280 header_dropdown
[i
] = ConstructHeaderFooterDropdown(header_footer_str
[i
].get());
281 // Those 4 magic numbers in the middle provide the position in the table.
282 // The last two numbers mean 2 px padding on every side.
283 gtk_table_attach(GTK_TABLE(header_footer_table
), header_dropdown
[i
], i
, (i
+ 1),
284 0, 1, (GtkAttachOptions
) 0, (GtkAttachOptions
) 0, 2, 2);
287 const char labelKeys
[][7] = {"left", "center", "right"};
288 for (unsigned int i
= 0; i
< ArrayLength(labelKeys
); i
++) {
289 gtk_table_attach(GTK_TABLE(header_footer_table
),
290 gtk_label_new(GetUTF8FromBundle(labelKeys
[i
]).get()),
291 i
, (i
+ 1), 1, 2, (GtkAttachOptions
) 0, (GtkAttachOptions
) 0, 2, 2);
294 aSettings
->GetFooterStrLeft(header_footer_str
[0]);
295 aSettings
->GetFooterStrCenter(header_footer_str
[1]);
296 aSettings
->GetFooterStrRight(header_footer_str
[2]);
298 for (unsigned int i
= 0; i
< ArrayLength(footer_dropdown
); i
++) {
299 footer_dropdown
[i
] = ConstructHeaderFooterDropdown(header_footer_str
[i
].get());
300 gtk_table_attach(GTK_TABLE(header_footer_table
), footer_dropdown
[i
], i
, (i
+ 1),
301 2, 3, (GtkAttachOptions
) 0, (GtkAttachOptions
) 0, 2, 2);
305 gtk_container_add(GTK_CONTAINER(header_footer_container
), header_footer_table
);
307 GtkWidget
* header_footer_vertical_squasher
= gtk_vbox_new(FALSE
, 0);
308 gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher
), header_footer_label
, FALSE
, FALSE
, 0);
309 gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher
), header_footer_container
, FALSE
, FALSE
, 0);
311 // Construction of everything
312 gtk_box_pack_start(GTK_BOX(custom_options_tab
), print_frames_label
, FALSE
, FALSE
, 0);
313 gtk_box_pack_start(GTK_BOX(custom_options_tab
), frames_radio_container
, FALSE
, FALSE
, 0);
314 gtk_box_pack_start(GTK_BOX(custom_options_tab
), check_buttons_container
, FALSE
, FALSE
, 10); // 10px padding
315 gtk_box_pack_start(GTK_BOX(custom_options_tab
), appearance_vertical_squasher
, FALSE
, FALSE
, 10);
316 gtk_box_pack_start(GTK_BOX(custom_options_tab
), header_footer_vertical_squasher
, FALSE
, FALSE
, 0);
318 gtk_print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(dialog
), custom_options_tab
, tab_label
);
319 gtk_widget_show_all(custom_options_tab
);
322 NS_ConvertUTF16toUTF8
323 nsPrintDialogWidgetGTK::GetUTF8FromBundle(const char *aKey
)
325 nsAutoString intlString
;
326 printBundle
->GetStringFromName(aKey
, intlString
);
327 return NS_ConvertUTF16toUTF8(intlString
); // Return the actual object so we don't lose reference
331 nsPrintDialogWidgetGTK::OptionWidgetToString(GtkWidget
*dropdown
)
333 gint index
= gtk_combo_box_get_active(GTK_COMBO_BOX(dropdown
));
335 NS_ASSERTION(index
<= CUSTOM_VALUE_INDEX
, "Index of dropdown is higher than expected!");
337 if (index
== CUSTOM_VALUE_INDEX
)
338 return (const char*) g_object_get_data(G_OBJECT(dropdown
), "custom-text");
340 return header_footer_tags
[index
];
344 nsPrintDialogWidgetGTK::Run()
346 const gint response
= gtk_dialog_run(GTK_DIALOG(dialog
));
347 gtk_widget_hide(dialog
);
352 nsPrintDialogWidgetGTK::ExportFramePrinting(nsIPrintSettings
*aNS
, GtkPrintSettings
*aSettings
)
354 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_as_laid_out
)))
355 aNS
->SetPrintFrameType(nsIPrintSettings::kFramesAsIs
);
356 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_selected_frame
)))
357 aNS
->SetPrintFrameType(nsIPrintSettings::kSelectedFrame
);
358 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_separate_frames
)))
359 aNS
->SetPrintFrameType(nsIPrintSettings::kEachFrameSep
);
361 aNS
->SetPrintFrameType(nsIPrintSettings::kNoFrames
);
365 nsPrintDialogWidgetGTK::ExportHeaderFooter(nsIPrintSettings
*aNS
)
367 const char* header_footer_str
;
368 header_footer_str
= OptionWidgetToString(header_dropdown
[0]);
369 aNS
->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(header_footer_str
));
371 header_footer_str
= OptionWidgetToString(header_dropdown
[1]);
372 aNS
->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(header_footer_str
));
374 header_footer_str
= OptionWidgetToString(header_dropdown
[2]);
375 aNS
->SetHeaderStrRight(NS_ConvertUTF8toUTF16(header_footer_str
));
377 header_footer_str
= OptionWidgetToString(footer_dropdown
[0]);
378 aNS
->SetFooterStrLeft(NS_ConvertUTF8toUTF16(header_footer_str
));
380 header_footer_str
= OptionWidgetToString(footer_dropdown
[1]);
381 aNS
->SetFooterStrCenter(NS_ConvertUTF8toUTF16(header_footer_str
));
383 header_footer_str
= OptionWidgetToString(footer_dropdown
[2]);
384 aNS
->SetFooterStrRight(NS_ConvertUTF8toUTF16(header_footer_str
));
388 nsPrintDialogWidgetGTK::ImportSettings(nsIPrintSettings
*aNSSettings
)
390 NS_PRECONDITION(aNSSettings
, "aSettings must not be null");
391 NS_ENSURE_TRUE(aNSSettings
, NS_ERROR_FAILURE
);
393 nsCOMPtr
<nsPrintSettingsGTK
> aNSSettingsGTK(do_QueryInterface(aNSSettings
));
395 return NS_ERROR_FAILURE
;
397 GtkPrintSettings
* settings
= aNSSettingsGTK
->GetGtkPrintSettings();
398 GtkPageSetup
* setup
= aNSSettingsGTK
->GetGtkPageSetup();
401 aNSSettings
->GetShrinkToFit(&geckoBool
);
402 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle
), geckoBool
);
404 aNSSettings
->GetPrintBGColors(&geckoBool
);
405 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle
), geckoBool
);
407 aNSSettings
->GetPrintBGImages(&geckoBool
);
408 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle
), geckoBool
);
410 gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog
), settings
);
411 gtk_print_unix_dialog_set_page_setup(GTK_PRINT_UNIX_DIALOG(dialog
), setup
);
417 nsPrintDialogWidgetGTK::ExportSettings(nsIPrintSettings
*aNSSettings
)
419 NS_PRECONDITION(aNSSettings
, "aSettings must not be null");
420 NS_ENSURE_TRUE(aNSSettings
, NS_ERROR_FAILURE
);
422 GtkPrintSettings
* settings
= gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog
));
423 GtkPageSetup
* setup
= gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog
));
424 GtkPrinter
* printer
= gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(dialog
));
425 if (settings
&& setup
&& printer
) {
426 ExportFramePrinting(aNSSettings
, settings
);
427 ExportHeaderFooter(aNSSettings
);
429 aNSSettings
->SetOutputFormat(nsIPrintSettings::kOutputFormatNative
);
431 // Print-to-file is true by default. This must be turned off or else printing won't occur!
432 // (We manually copy the spool file when this flag is set, because we love our embedders)
433 // Even if it is print-to-file in GTK's case, GTK does The Right Thing when we send the job.
434 aNSSettings
->SetPrintToFile(false);
436 aNSSettings
->SetShrinkToFit(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle
)));
438 aNSSettings
->SetPrintBGColors(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle
)));
439 aNSSettings
->SetPrintBGImages(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle
)));
441 // Try to save native settings in the session object
442 nsCOMPtr
<nsPrintSettingsGTK
> aNSSettingsGTK(do_QueryInterface(aNSSettings
));
443 if (aNSSettingsGTK
) {
444 aNSSettingsGTK
->SetGtkPrintSettings(settings
);
445 aNSSettingsGTK
->SetGtkPageSetup(setup
);
446 aNSSettingsGTK
->SetGtkPrinter(printer
);
447 bool printSelectionOnly
;
448 if (useNativeSelection
) {
449 _GtkPrintPages pageSetting
= (_GtkPrintPages
)gtk_print_settings_get_print_pages(settings
);
450 printSelectionOnly
= (pageSetting
== _GTK_PRINT_PAGES_SELECTION
);
452 printSelectionOnly
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(selection_only_toggle
));
454 aNSSettingsGTK
->SetForcePrintSelectionOnly(printSelectionOnly
);
459 g_object_unref(settings
);
464 nsPrintDialogWidgetGTK::ConstructHeaderFooterDropdown(const char16_t
*currentString
)
466 GtkWidget
* dropdown
= gtk_combo_box_text_new();
467 const char hf_options
[][22] = {"headerFooterBlank", "headerFooterTitle",
468 "headerFooterURL", "headerFooterDate",
469 "headerFooterPage", "headerFooterPageTotal",
470 "headerFooterCustom"};
472 for (unsigned int i
= 0; i
< ArrayLength(hf_options
); i
++) {
473 gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(dropdown
), nullptr,
474 GetUTF8FromBundle(hf_options
[i
]).get());
477 bool shouldBeCustom
= true;
478 NS_ConvertUTF16toUTF8
currentStringUTF8(currentString
);
480 for (unsigned int i
= 0; i
< ArrayLength(header_footer_tags
); i
++) {
481 if (!strcmp(currentStringUTF8
.get(), header_footer_tags
[i
])) {
482 gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown
), i
);
483 g_object_set_data(G_OBJECT(dropdown
), "previous-active", GINT_TO_POINTER(i
));
484 shouldBeCustom
= false;
489 if (shouldBeCustom
) {
490 gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown
), CUSTOM_VALUE_INDEX
);
491 g_object_set_data(G_OBJECT(dropdown
), "previous-active", GINT_TO_POINTER(CUSTOM_VALUE_INDEX
));
492 char* custom_string
= strdup(currentStringUTF8
.get());
493 g_object_set_data_full(G_OBJECT(dropdown
), "custom-text", custom_string
, (GDestroyNotify
) free
);
496 g_signal_connect(dropdown
, "changed", (GCallback
) ShowCustomDialog
, dialog
);
500 NS_IMPL_ISUPPORTS(nsPrintDialogServiceGTK
, nsIPrintDialogService
)
502 nsPrintDialogServiceGTK::nsPrintDialogServiceGTK()
506 nsPrintDialogServiceGTK::~nsPrintDialogServiceGTK()
511 nsPrintDialogServiceGTK::Init()
517 nsPrintDialogServiceGTK::Show(nsPIDOMWindowOuter
*aParent
,
518 nsIPrintSettings
*aSettings
,
519 nsIWebBrowserPrint
*aWebBrowserPrint
)
521 NS_PRECONDITION(aParent
, "aParent must not be null");
522 NS_PRECONDITION(aSettings
, "aSettings must not be null");
524 nsPrintDialogWidgetGTK
printDialog(aParent
, aSettings
);
525 nsresult rv
= printDialog
.ImportSettings(aSettings
);
527 NS_ENSURE_SUCCESS(rv
, rv
);
529 const gint response
= printDialog
.Run();
533 case GTK_RESPONSE_OK
: // Proceed
534 rv
= printDialog
.ExportSettings(aSettings
);
537 case GTK_RESPONSE_CANCEL
:
538 case GTK_RESPONSE_CLOSE
:
539 case GTK_RESPONSE_DELETE_EVENT
:
540 case GTK_RESPONSE_NONE
:
544 case GTK_RESPONSE_APPLY
: // Print preview
546 NS_WARNING("Unexpected response");
553 nsPrintDialogServiceGTK::ShowPageSetup(nsPIDOMWindowOuter
*aParent
,
554 nsIPrintSettings
*aNSSettings
)
556 NS_PRECONDITION(aParent
, "aParent must not be null");
557 NS_PRECONDITION(aNSSettings
, "aSettings must not be null");
558 NS_ENSURE_TRUE(aNSSettings
, NS_ERROR_FAILURE
);
560 nsCOMPtr
<nsIWidget
> widget
= WidgetUtils::DOMWindowToWidget(aParent
);
561 NS_ASSERTION(widget
, "Need a widget for dialog to be modal.");
562 GtkWindow
* gtkParent
= get_gtk_window_for_nsiwidget(widget
);
563 NS_ASSERTION(gtkParent
, "Need a GTK window for dialog to be modal.");
565 nsCOMPtr
<nsPrintSettingsGTK
> aNSSettingsGTK(do_QueryInterface(aNSSettings
));
567 return NS_ERROR_FAILURE
;
569 // We need to init the prefs here because aNSSettings in its current form is a dummy in both uses of the word
570 nsCOMPtr
<nsIPrintSettingsService
> psService
= do_GetService("@mozilla.org/gfx/printsettings-service;1");
573 aNSSettings
->GetPrinterName(printName
);
574 if (printName
.IsVoid()) {
575 psService
->GetDefaultPrinterName(printName
);
576 aNSSettings
->SetPrinterName(printName
);
578 psService
->InitPrintSettingsFromPrefs(aNSSettings
, true, nsIPrintSettings::kInitSaveAll
);
581 GtkPrintSettings
* gtkSettings
= aNSSettingsGTK
->GetGtkPrintSettings();
582 GtkPageSetup
* oldPageSetup
= aNSSettingsGTK
->GetGtkPageSetup();
584 GtkPageSetup
* newPageSetup
= gtk_print_run_page_setup_dialog(gtkParent
, oldPageSetup
, gtkSettings
);
586 aNSSettingsGTK
->SetGtkPageSetup(newPageSetup
);
588 // Now newPageSetup has a refcount of 2 (SetGtkPageSetup will addref), put it to 1 so if
589 // this gets replaced we don't leak.
590 g_object_unref(newPageSetup
);
593 psService
->SavePrintSettingsToPrefs(aNSSettings
, true, nsIPrintSettings::kInitSaveAll
);