Skip to content

Commit b0fd7cf

Browse files
codebyterejkleinsc
andauthored
fix: honor pageRanges when printing (electron#25600)
* fix: honor pageRanges when printing * Update docs/api/web-contents.md Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
1 parent a56c1d3 commit b0fd7cf

File tree

5 files changed

+144
-14
lines changed

5 files changed

+144
-14
lines changed

docs/api/web-contents.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,9 +1324,9 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
13241324
* `pagesPerSheet` Number (optional) - The number of pages to print per page sheet.
13251325
* `collate` Boolean (optional) - Whether the web page should be collated.
13261326
* `copies` Number (optional) - The number of copies of the web page to print.
1327-
* `pageRanges` Record<string, number> (optional) - The page range to print.
1328-
* `from` Number - the start page.
1329-
* `to` Number - the end page.
1327+
* `pageRanges` Object[] (optional) - The page range to print. On macOS, only one range is honored.
1328+
* `from` Number - Index of the first page to print (0-based).
1329+
* `to` Number - Index of the last page to print (inclusive) (0-based).
13301330
* `duplexMode` String (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
13311331
* `dpi` Record<string, number> (optional)
13321332
* `horizontal` Number (optional) - The horizontal dpi.
@@ -1352,10 +1352,10 @@ Example usage:
13521352
const options = {
13531353
silent: true,
13541354
deviceName: 'My-Printer',
1355-
pageRanges: {
1355+
pageRanges: [{
13561356
from: 0,
13571357
to: 1
1358-
}
1358+
}]
13591359
}
13601360
win.webContents.print(options, (success, errorType) => {
13611361
if (!success) console.log(errorType)
@@ -1373,8 +1373,8 @@ win.webContents.print(options, (success, errorType) => {
13731373
default margin, 1 for no margin, and 2 for minimum margin.
13741374
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
13751375
* `pageRanges` Record<string, number> (optional) - The page range to print.
1376-
* `from` Number - zero-based index of the first page to print.
1377-
* `to` Number - zero-based index of the last page to print (inclusive).
1376+
* `from` Number - Index of the first page to print (0-based).
1377+
* `to` Number - Index of the last page to print (inclusive) (0-based).
13781378
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
13791379
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
13801380
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.

docs/api/webview-tag.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -560,9 +560,9 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
560560
* `pagesPerSheet` Number (optional) - The number of pages to print per page sheet.
561561
* `collate` Boolean (optional) - Whether the web page should be collated.
562562
* `copies` Number (optional) - The number of copies of the web page to print.
563-
* `pageRanges` Record<string, number> (optional) - The page range to print.
564-
* `from` Number - zero-based index of the first page to print.
565-
* `to` Number - zero-based index of the last page to print (inclusive).
563+
* `pageRanges` Object[] (optional) - The page range to print.
564+
* `from` Number - Index of the first page to print (0-based).
565+
* `to` Number - Index of the last page to print (inclusive) (0-based).
566566
* `duplexMode` String (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
567567
* `dpi` Record<string, number> (optional)
568568
* `horizontal` Number (optional) - The horizontal dpi.
@@ -588,8 +588,8 @@ Prints `webview`'s web page. Same as `webContents.print([options])`.
588588
and `width` in microns.
589589
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
590590
* `pageRanges` Record<string, number> (optional) - The page range to print.
591-
* `from` Number - the first page to print.
592-
* `to` Number - the last page to print (inclusive).
591+
* `from` Number - Index of the first page to print (0-based).
592+
* `to` Number - Index of the last page to print (inclusive) (0-based).
593593
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
594594
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
595595
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.

patches/chromium/.patches

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,4 @@ fix_use_electron_generated_resources.patch
102102
chore_expose_v8_initialization_isolate_callbacks.patch
103103
rename_the_v8_context_snapshot_on_arm64_macos_builds.patch
104104
crashpad-initialize-logging.patch
105+
fix_properly_honor_printing_page_ranges.patch
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2+
From: Shelley Vohr <shelley.vohr@gmail.com>
3+
Date: Wed, 23 Sep 2020 11:16:12 -0700
4+
Subject: fix: properly honor printing page ranges
5+
6+
The print ranges in Chromium's print job settings were not being properly
7+
plumbed through to PMPrintSettings on mcOS. This fixes that by setting
8+
them should they exist.
9+
10+
diff --git a/printing/printing_context_mac.h b/printing/printing_context_mac.h
11+
index 909aaf6ce803fed32eb1c64c0abcf272731762da..ba431655fe5894c7d9b04464ea36307a145ac198 100644
12+
--- a/printing/printing_context_mac.h
13+
+++ b/printing/printing_context_mac.h
14+
@@ -82,6 +82,10 @@ class PRINTING_EXPORT PrintingContextMac : public PrintingContext {
15+
// Returns true if the orientation was set.
16+
bool SetOrientationIsLandscape(bool landscape);
17+
18+
+ // Set the page range in native print info object.
19+
+ // Returns true if the range was set.
20+
+ bool SetPrintRangeInPrintSettings(const PageRanges& ranges);
21+
+
22+
// Sets duplex mode in PMPrintSettings.
23+
// Returns true if duplex mode is set.
24+
bool SetDuplexModeInPrintSettings(mojom::DuplexMode mode);
25+
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
26+
index 51c8ff31497fd03842ac9e7da4eab8a5919ec898..53e11ca26e82f2eac18a3465cabde2605b061319 100644
27+
--- a/printing/printing_context_mac.mm
28+
+++ b/printing/printing_context_mac.mm
29+
@@ -188,7 +188,8 @@ PMPaper MatchPaper(CFArrayRef paper_list,
30+
!SetCopiesInPrintSettings(settings_->copies()) ||
31+
!SetCollateInPrintSettings(settings_->collate()) ||
32+
!SetDuplexModeInPrintSettings(settings_->duplex_mode()) ||
33+
- !SetOutputColor(static_cast<int>(settings_->color()))) {
34+
+ !SetOutputColor(static_cast<int>(settings_->color())) ||
35+
+ !SetPrintRangeInPrintSettings(settings_->ranges())) {
36+
return OnError();
37+
}
38+
}
39+
@@ -341,6 +342,22 @@ PMPaper MatchPaper(CFArrayRef paper_list,
40+
return PMSetCopies(print_settings, copies, false) == noErr;
41+
}
42+
43+
+bool PrintingContextMac::SetPrintRangeInPrintSettings(const PageRanges& ranges) {
44+
+ // Default is already NSPrintAllPages - we can safely bail.
45+
+ if (ranges.empty())
46+
+ return true;
47+
+
48+
+ auto* print_settings =
49+
+ static_cast<PMPrintSettings>([print_info_.get() PMPrintSettings]);
50+
+
51+
+ // macOS does not allow multiple ranges, so pluck the first.
52+
+ auto range = ranges.front();
53+
+ bool set_first_page = PMSetFirstPage(print_settings, range.from + 1, false) == noErr;
54+
+ bool set_last_page = PMSetLastPage(print_settings, range.to + 1, false) == noErr;
55+
+
56+
+ return set_first_page && set_last_page;
57+
+}
58+
+
59+
bool PrintingContextMac::SetCollateInPrintSettings(bool collate) {
60+
PMPrintSettings print_settings =
61+
static_cast<PMPrintSettings>([print_info_.get() PMPrintSettings]);
62+
diff --git a/printing/printing_context_system_dialog_win.cc b/printing/printing_context_system_dialog_win.cc
63+
index d3c8677f30d72efc49b28f293260c74c7b8d8b4e..f6e66aaa58ab1881d64dcbb320ae8b5ac7631b28 100644
64+
--- a/printing/printing_context_system_dialog_win.cc
65+
+++ b/printing/printing_context_system_dialog_win.cc
66+
@@ -52,14 +52,28 @@ void PrintingContextSystemDialogWin::AskUserForSettings(
67+
PRINTPAGERANGE ranges[32];
68+
dialog_options.nStartPage = START_PAGE_GENERAL;
69+
if (max_pages) {
70+
- // Default initialize to print all the pages.
71+
memset(ranges, 0, sizeof(ranges));
72+
- ranges[0].nFromPage = 1;
73+
- ranges[0].nToPage = max_pages;
74+
- dialog_options.nPageRanges = 1;
75+
- dialog_options.nMaxPageRanges = base::size(ranges);
76+
+
77+
+ auto page_ranges = settings_->ranges();
78+
+ if (!page_ranges.empty()) {
79+
+ for (size_t i = 0; i < page_ranges.size(); i++) {
80+
+ auto range = page_ranges[i];
81+
+ ranges[i].nFromPage = range.from + 1;
82+
+ ranges[i].nToPage = range.to + 1;
83+
+ }
84+
+ dialog_options.nPageRanges = page_ranges.size();
85+
+
86+
+ // Ensure the Pages radio button is selected.
87+
+ dialog_options.Flags |= PD_PAGENUMS;
88+
+ } else {
89+
+ ranges[0].nFromPage = 1;
90+
+ ranges[0].nToPage = max_pages;
91+
+ dialog_options.nPageRanges = 1;
92+
+ }
93+
+
94+
dialog_options.nMinPage = 1;
95+
dialog_options.nMaxPage = max_pages;
96+
+ dialog_options.nMaxPageRanges = base::size(ranges);
97+
dialog_options.lpPageRanges = ranges;
98+
} else {
99+
// No need to bother, we don't know how many pages are available.
100+
diff --git a/ui/gtk/printing/print_dialog_gtk.cc b/ui/gtk/printing/print_dialog_gtk.cc
101+
index f2ed36e1258f4f3ef1bfce972e215e3d5d7335b6..5b38bf1369a68546f0aeea8948abba995c65e7f7 100644
102+
--- a/ui/gtk/printing/print_dialog_gtk.cc
103+
+++ b/ui/gtk/printing/print_dialog_gtk.cc
104+
@@ -239,6 +239,24 @@ void PrintDialogGtk::UpdateSettings(
105+
106+
gtk_print_settings_set_n_copies(gtk_settings_, settings->copies());
107+
gtk_print_settings_set_collate(gtk_settings_, settings->collate());
108+
+
109+
+ auto print_ranges = settings->ranges();
110+
+ if (!print_ranges.empty()) {
111+
+ // Tell the system that we only intend to print a subset of pages.
112+
+ gtk_print_settings_set_print_pages(gtk_settings_, GTK_PRINT_PAGES_RANGES);
113+
+
114+
+ GtkPageRange* ranges;
115+
+ ranges = g_new(GtkPageRange, print_ranges.size());
116+
+ for (size_t i = 0; i < print_ranges.size(); i++) {
117+
+ auto range = print_ranges[i];
118+
+ ranges[i].start = range.from;
119+
+ ranges[i].end = range.to;
120+
+ }
121+
+
122+
+ gtk_print_settings_set_page_ranges(gtk_settings_, ranges, 1);
123+
+ g_free(ranges);
124+
+ }
125+
+
126+
if (settings->dpi_horizontal() > 0 && settings->dpi_vertical() > 0) {
127+
gtk_print_settings_set_resolution_xy(
128+
gtk_settings_, settings->dpi_horizontal(), settings->dpi_vertical());

shell/browser/api/electron_api_web_contents.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,8 +2168,9 @@ void WebContents::Print(gin::Arguments* args) {
21682168
int from, to;
21692169
if (range.Get("from", &from) && range.Get("to", &to)) {
21702170
base::Value range(base::Value::Type::DICTIONARY);
2171-
range.SetIntKey(printing::kSettingPageRangeFrom, from);
2172-
range.SetIntKey(printing::kSettingPageRangeTo, to);
2171+
// Chromium uses 1-based page ranges, so increment each by 1.
2172+
range.SetIntKey(printing::kSettingPageRangeFrom, from + 1);
2173+
range.SetIntKey(printing::kSettingPageRangeTo, to + 1);
21732174
page_range_list.Append(std::move(range));
21742175
} else {
21752176
continue;

0 commit comments

Comments
 (0)