Bug 1666734 - Add two-sided printing checkbox to print UI r=sfoster,fluent-reviewers,flod,AlaskanEmily

This patch adds a new checkbox to the print UI for two-sided printing.
The checkbox is only visible if the currently selected printer supports
two-sided printing.

Notable Changes:
  - Add new section and checkbox for two-sided printing.
  - Add new getter to settings proxy for supportsDuplex.
  - Add new setter/getter to settings proxy for printDuplex.
  - Add new test for no duplex with PDF printer.
  - Add new test for toggle duplex in portrait orientation.
  - Add new test for toggle duplex in landscape orientation.
  - Add new test for toggle orientation with duplex checked.
  - Correctly set duple mode in GTK print settings.

Depends on D94026

Differential Revision: https://phabricator.services.mozilla.com/D93621
This commit is contained in:
Erik Nordin 2020-11-06 01:14:15 +00:00
Родитель 92af1fd6cc
Коммит f3863e87b5
8 изменённых файлов: 228 добавлений и 3 удалений

Просмотреть файл

@ -24,8 +24,10 @@ async function run() {
isnot(printer.name, "", "Printer name should never be empty.");
info(printer.name);
let printerInfo = await printer.printerInfo;
for (let paper of printerInfo.paperList) {
info("duplex(" + printer.supportsDuplex + ")");
let paperList = await printer.paperList;
for (let paper of paperList) {
paper.QueryInterface(Ci.nsIPaper);
info(`${paper.name}: ${paper.width}x${paper.height}`);

Просмотреть файл

@ -21,6 +21,7 @@ async function run() {
for (let printer of printers) {
printer.QueryInterface(Ci.nsIPrinter);
info(printer.name);
info("duplex(" + await printer.supportsDuplex + ")");
const printerInfo = await printer.printerInfo;
const settings = printerInfo.defaultSettings;
@ -29,7 +30,6 @@ async function run() {
is(typeof settings.printerName, "string", "Printer name should be a string.");
is(settings.printerName, printer.name, "Print settings' printer should match the printer that created them.");
console.log(typeof settings.paperWidth);
is(typeof settings.paperId, "string", "Paper ID should never be null.");
is(typeof settings.paperWidth, "number", "Paper width should never be null.");
is(typeof settings.paperHeight, "number", "Paper height should never be null.");

Просмотреть файл

@ -168,6 +168,14 @@
<div id="margins-select" is="margins-select" class="margins-select row"></div>
</section>
<section id="two-sided-printing" class="section-block">
<label class="block-label" data-l10n-id="printui-two-sided-printing"></label>
<div class="row cols-2">
<input is="setting-checkbox" type="checkbox" id="duplex-enabled" data-setting-name="printDuplex">
<label for="duplex-enabled" data-l10n-id="printui-duplex-checkbox"></label>
</div>
</section>
<section id="more-settings-options" class="section-block">
<label class="block-label" data-l10n-id="printui-options"></label>
<div class="row cols-2">

Просмотреть файл

@ -130,6 +130,7 @@ var PrintEventHandler = {
printInColor: Ci.nsIPrintSettings.kInitSaveInColor,
scaling: Ci.nsIPrintSettings.kInitSaveScaling,
shrinkToFit: Ci.nsIPrintSettings.kInitSaveShrinkToFit,
printDuplex: Ci.nsIPrintSettings.kInitSaveDuplex,
printFootersHeaders:
Ci.nsIPrintSettings.kInitSaveHeaderLeft |
Ci.nsIPrintSettings.kInitSaveHeaderCenter |
@ -404,6 +405,7 @@ var PrintEventHandler = {
} else if (!this.viewSettings.supportsMonochrome) {
settingsToUpdate.printInColor = true;
}
if (
settingsToUpdate.printInColor != this._userChangedSettings.printInColor
) {
@ -989,10 +991,12 @@ var PrintSettingsViewProxy = {
let basePrinterInfo;
try {
[
printerInfo.supportsDuplex,
printerInfo.supportsColor,
printerInfo.supportsMonochrome,
basePrinterInfo,
] = await Promise.all([
printerInfo.printer.supportsDuplex,
printerInfo.printer.supportsColor,
printerInfo.printer.supportsMonochrome,
printerInfo.printer.printerInfo,
@ -1156,6 +1160,12 @@ var PrintSettingsViewProxy = {
};
});
case "supportsDuplex":
return this.availablePrinters[target.printerName].supportsDuplex;
case "printDuplex":
return target.duplex;
case "printBackgrounds":
return target.printBGImages || target.printBGColors;
@ -1243,6 +1253,12 @@ var PrintSettingsViewProxy = {
target.printBGColors = value;
break;
case "printDuplex":
target.duplex = value
? Ci.nsIPrintSettings.kDuplexHorizontal
: Ci.nsIPrintSettings.kSimplex;
break;
case "printFootersHeaders":
// To disable header & footers, set them all to empty.
// To enable, restore default values for each of the header & footer settings.
@ -1555,6 +1571,8 @@ class PrintUIForm extends PrintUIControlMixin(HTMLFormElement) {
AppConstants.platform === "win" && !settings.defaultSystemPrinter;
this.querySelector("#copies").hidden = settings.willSaveToFile;
this.querySelector("#two-sided-printing").hidden = !settings.supportsDuplex;
}
enable() {

Просмотреть файл

@ -18,6 +18,8 @@ skip-if = os == "mac"
[browser_print_paper_sizes.js]
[browser_pdf_printer_settings.js]
[browser_print_bcg_id_overflow.js]
[browser_print_duplex.js]
skip-if = (verify && (os == 'mac')) # bug 1675609
[browser_print_margins.js]
[browser_print_selection.js]
[browser_print_page_range.js]

Просмотреть файл

@ -0,0 +1,174 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
add_task(async function testPDFPrinterIsNonDuplex() {
await PrintHelper.withTestPage(async helper => {
await helper.startPrint();
await helper.openMoreSettings();
is(
helper.settings.printerName,
"Mozilla Save to PDF",
"Mozilla Save to PDF is the current printer."
);
const duplexSection = helper.get("two-sided-printing");
ok(
duplexSection.hidden,
"The two-sided printing section should be hidden when the printer does not support duplex."
);
helper.assertSettingsMatch({ duplex: Ci.nsIPrintSettings.kSimplex });
await helper.closeDialog();
});
});
add_task(async function testToggleDuplexWithPortraitOrientation() {
const mockPrinterName = "DuplexWithPortrait";
await PrintHelper.withTestPage(async helper => {
const printer = helper.addMockPrinter(mockPrinterName);
printer.supportsDuplex = Promise.resolve(true);
await helper.startPrint();
await helper.dispatchSettingsChange({ printerName: mockPrinterName });
await helper.awaitAnimationFrame();
await helper.openMoreSettings();
is(
helper.settings.printerName,
mockPrinterName,
"The Fake Printer is current printer"
);
const duplexSection = helper.get("two-sided-printing");
ok(
!duplexSection.hidden,
"The two-sided printing section should not be hidden when the printer supports duplex."
);
helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kPortraitOrientation,
duplex: Ci.nsIPrintSettings.kSimplex,
});
await helper.click(helper.get("duplex-enabled"));
helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kPortraitOrientation,
duplex: Ci.nsIPrintSettings.kDuplexHorizontal,
});
await helper.click(helper.get("duplex-enabled"));
helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kPortraitOrientation,
duplex: Ci.nsIPrintSettings.kSimplex,
});
await helper.closeDialog();
});
});
add_task(async function testToggleDuplexWithLandscapeOrientation() {
const mockPrinterName = "DuplexWithLandscape";
await PrintHelper.withTestPage(async helper => {
const printer = helper.addMockPrinter(mockPrinterName);
printer.supportsDuplex = Promise.resolve(true);
await helper.startPrint();
await helper.dispatchSettingsChange({ printerName: mockPrinterName });
await helper.awaitAnimationFrame();
await helper.openMoreSettings();
is(
helper.settings.printerName,
mockPrinterName,
"The Fake Printer is current printer"
);
const duplexSection = helper.get("two-sided-printing");
ok(
!duplexSection.hidden,
"The two-sided printing section should not be hidden when the printer supports duplex."
);
await helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kPortraitOrientation,
duplex: Ci.nsIPrintSettings.kSimplex,
});
await helper.dispatchSettingsChange({ orientation: 1 });
await helper.awaitAnimationFrame();
await helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kLandscapeOrientation,
duplex: Ci.nsIPrintSettings.kSimplex,
});
await helper.click(helper.get("duplex-enabled"));
await helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kLandscapeOrientation,
duplex: Ci.nsIPrintSettings.kDuplexHorizontal,
});
await helper.click(helper.get("duplex-enabled"));
await helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kLandscapeOrientation,
duplex: Ci.nsIPrintSettings.kSimplex,
});
await helper.closeDialog();
});
});
add_task(async function testSwitchOrientationWithDuplexEnabled() {
const mockPrinterName = "ToggleOrientationPrinter";
await PrintHelper.withTestPage(async helper => {
const printer = helper.addMockPrinter(mockPrinterName);
printer.supportsDuplex = Promise.resolve(true);
await helper.startPrint();
await helper.dispatchSettingsChange({ printerName: mockPrinterName });
await helper.awaitAnimationFrame();
await helper.openMoreSettings();
is(
helper.settings.printerName,
mockPrinterName,
"The Fake Printer is current printer"
);
const duplexSection = helper.get("two-sided-printing");
ok(
!duplexSection.hidden,
"The two-sided printing section should not be hidden when the printer supports duplex."
);
await helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kPortraitOrientation,
duplex: Ci.nsIPrintSettings.kSimplex,
});
await helper.click(helper.get("duplex-enabled"));
await helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kPortraitOrientation,
duplex: Ci.nsIPrintSettings.kDuplexHorizontal,
});
await helper.dispatchSettingsChange({ orientation: 1 });
await helper.awaitAnimationFrame();
await helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kLandscapeOrientation,
duplex: Ci.nsIPrintSettings.kDuplexHorizontal,
});
await helper.dispatchSettingsChange({ orientation: 0 });
await helper.awaitAnimationFrame();
await helper.assertSettingsMatch({
orientation: Ci.nsIPrintSettings.kPortraitOrientation,
duplex: Ci.nsIPrintSettings.kDuplexHorizontal,
});
await helper.closeDialog();
});
});

Просмотреть файл

@ -50,6 +50,10 @@ printui-scale-fit-to-page-width = Fit to page width
# Label for input control where user can set the scale percentage
printui-scale-pcent = Scale
# Section title (noun) for the two-sided print options
printui-two-sided-printing = Two-sided printing
printui-duplex-checkbox = Print on both sides
# Section title for miscellaneous print options
printui-options = Options
printui-headers-footers-checkbox = Print headers and footers

Просмотреть файл

@ -717,5 +717,22 @@ nsPrintSettingsGTK::SetDuplex(int32_t aDuplex) {
"value is out of bounds for GtkPrintDuplex enum");
gtk_print_settings_set_duplex(mPrintSettings,
static_cast<GtkPrintDuplex>(aDuplex));
// We want to set the GTK CUPS Duplex setting in addition to calling
// gtk_print_settings_set_duplex(). Some systems may look for one, or the
// other, so it is best to set them both consistently.
constexpr char kCupsDuplex[] = "cups-Duplex";
switch (aDuplex) {
case GTK_PRINT_DUPLEX_SIMPLEX:
gtk_print_settings_set(mPrintSettings, kCupsDuplex, "None");
break;
case GTK_PRINT_DUPLEX_HORIZONTAL:
gtk_print_settings_set(mPrintSettings, kCupsDuplex, "DuplexNoTumble");
break;
case GTK_PRINT_DUPLEX_VERTICAL:
gtk_print_settings_set(mPrintSettings, kCupsDuplex, "DuplexTumble");
break;
}
return NS_OK;
}