Commit Graph
12 Commits
Author SHA1 Message Date
midasdf d1a02c7f2f Merge remote-tracking branch 'origin/main' into pr
# Conflicts:
#	docs/target-app-parity.md
2026-11-01 22:50:04 +09:00
midasdf d461820117 Merge origin/main into jp/print-paper-sizes
docs/target-app-parity.md status line: main's newest (2026-10-27) plus the Japanese paper-size clause at its previous position; both tables kept main's rows.
2026-10-30 12:01:48 +09:00
David Mann fea300dd4c Merge origin/main into integration batch 10 2026-10-30 01:47:01 +01:00
Dylan M. Taylor 6fdd6bb1b7 packaging: Flatpak finds and prints to CUPS printers (#10196)
* packaging: Flatpak finds and prints to CUPS printers

The Print dialog listed no printers in the Flatpak: the runtime has libcups but not
lpstat/lp, the sandbox couldn't reach the CUPS socket, and driverless network printers
(lpstat -e) need Avahi. Bundle lpstat/lp/lpoptions from CUPS 2.4.20 (Apache-2.0,
statically linked, licence installed) and grant --socket=cups and
--system-talk-name=org.freedesktop.Avahi in both manifests.

* print: lp takes the job only when CUPS lists a printer; the only printer by default; ~/.cups read-only

Review (CodeRabbit) on bundling lp in the Flatpak:
- With lp present but CUPS down or empty, the job failed on lp instead of reaching the
  IPP route and the print portal. lp_route now gives up the route when lpstat lists no
  printer, before anything is submitted.
- With no printer named, no default and one queue, IPP picked it but lp failed. lp_route
  names the only printer.
- The sandbox ignored the user's default printer, saved options and client.conf server:
  grant ~/.cups read-only in both manifests.

* print: no printers for lp means the portal, not IPP; bounded listing; CUPS socket wrapper

Review:
- When lp is there but CUPS lists no printer, the job went to the IPP route, whose
  server detection ignores ~/.cups/client.conf and could print to a local default
  printer instead of the configured server. It now goes to the print portal, or fails
  with no portal.
- The lpstat listing before a job is bounded (10 s, then lp takes the job as before)
  and runs outside SPOOLER, which guards only Windows driver calls.
- Flatpak mounts the host's CUPS socket at /var/run/cups/cups.sock whatever path
  client.conf or CUPS_SERVER names; the CUPS tools now run through a wrapper that
  points a socket path missing in the sandbox there, leaving server names alone.

* packaging: redirect a custom CUPS socket only when it is the one Flatpak mounted

Review (CodeRabbit): Flatpak picks the socket it mounts at /var/run/cups/cups.sock
with stricter rules than CUPS (flatpak-run-cups.c: a socket CUPS_SERVER, else the
first line spelled exactly "ServerName /path" in ~/.cups/client.conf, else the
default), while CUPS reads the keyword in any case and takes the last ServerName. The
wrapper now redirects only when CUPS' socket is the one Flatpak chose, so a job can't
reach a different server; otherwise CUPS fails on the missing path.

* print: a printer listing past its deadline kills and reaps lpstat

Review: the 10 s limit stopped waiting but left a hung lpstat and its thread
running, so repeated print attempts could pile them up. photocraft now runs the two
lpstat listings itself (craft-print's lpstat_command and an equivalent lpstat -e,
parsed by printers_parsed) and kills and reaps each one at the shared deadline. The
output is read on a thread that ends with the process, so nothing outlives the job.

* packaging: never redirect a CUPS_SERVER the sandbox was given

Review (CodeRabbit): Flatpak picks the socket it mounts from the host's CUPS_SERVER,
so one set by flatpak run --env or an override may not be what it mounted. The
wrapper now leaves any CUPS_SERVER alone and redirects only a client.conf socket that
matches Flatpak's choice; otherwise CUPS fails on the missing path instead of
reaching a different server.

* packaging: point CUPS at the mounted socket only when it is the one Flatpak chose, else fail

Review (CodeRabbit): with a custom socket listed first and the default last in
~/.cups/client.conf, Flatpak mounts the custom one at /var/run/cups/cups.sock while
CUPS picks the last line, finds that path, and talks to the custom server. The
wrapper now compares CUPS' socket with Flatpak's choice even when the path exists:
equal, CUPS is pointed at the mount; different, the tool fails with an error instead
of reaching another server.

Also (CodeRabbit):
- A printer named in the job goes to lp even when CUPS lists none: listing can be
  forbidden while printing is not, and the portal can't honour a name.
- A failed lpstat -e (CUPS unreachable, listing forbidden) means the list can't be
  told, so lp takes the job, instead of an empty list sending it to the portal.
- A listing longer than 1 MiB counts as no answer, instead of growing without bound.
- The kill test checks the process with kill -0, which works on every Unix.
- docs/printing.md: the only-printer fallback is on the lp and IPP routes, and the
  portal is Linux only.
2026-10-29 18:51:10 -04:00
David MannandClaude Opus 5.5 03a0299bdb Merge PR #7795: Print: Scale to Fit Media fills the driver's printable area (#7782)
Conflicts with main's module moves resolved: driver_printable takes main's
spooler-held settings_for_layout (which already wraps the page query in
with_spooler) and drops the now unused settings/pg lines; take_turned_page and
its test move to dialogs/file_ui/print.rs and dialogs/file_ui/tests.rs;
crates/engine/src/cmd/print_cmds/tests.rs keeps main's version (the PR did
not change it in its own commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 20:15:41 +01:00
midasdf 7d884014d9 Print: show the canonical paper for a remembered alias
`file.print` accepts the customary names (はがき, L判, …) and remembers
the `paper` value as typed. On reopening, the Paper control passed that
alias straight to a menu keyed by the canonical `PAPERS` names, so a
valid remembered paper showed `—` instead of its preset.

Resolve the remembered name through `paper_size` and select the
matching `PAPERS` key. Custom arrays still open as Custom, and unknown
names stay as they are.

Tests: a remembered はがき reopens with はがき (100 × 148 mm) selected
and still lays the page out at 283.46 × 419.53 pt.

Docs: say that named papers use the table while custom [width, height]
values are accepted directly.
2026-10-23 02:28:33 +09:00
midasdf fadb558d6c Merge origin/main into jp/print-paper-sizes
Conflicts resolved keeping both sides, newest first:
- ROADMAP.md: status line, progress log, revision history
- docs/printing.md: Paper sizes then Positioning the preview
- docs/target-app-parity.md: status line, Print row, revision history
2026-10-23 02:02:40 +09:00
midasdf 161c1d21f7 Print: Japanese paper sizes (はがき, 往復はがき, JIS B5/B4, photo sizes)
Japanese printing had no paper of its own: the Print dialog and `file.print`
only offered letter/legal/tabloid/A3–A5/4x6/5x7, so a 年賀状 (New Year card),
はがき, a JIS B5 handout or an L判 photo could not be printed or exported to
PDF at its size. Add the customary papers at their exact metric sizes after the
existing entries, whose order and sizes are unchanged:

はがき 100×148 mm (283.46×419.53 pt), 往復はがき 148×200, JIS B5 182×257
(515.91×728.50), JIS B4 257×364 (728.50×1031.81), A6, L判 89×127
(252.28×360.00), 2L判 127×178, KG判 102×152, 六切 203×254 and 四切 254×305.

Names resolve case-, space- and punctuation-insensitively, and the customary
names are aliases (はがき/ハガキ/葉書/ポストカード, 往復はがき, JIS B5/B5 (JIS),
JIS B4/B4 (JIS), L判/Lサイズ/L-size, 2L判, KG判, 六切/6切, 四切/4切). The Print
dialog lists the sizes with their customary names and metric sizes, and the PDF
page (MediaBox) takes the paper's size.

Tests: `print_cmds::tests::japanese_paper_sizes_and_aliases` pins every size to
0.1 pt, the aliases and the unchanged existing papers;
`japanese_paper_sizes_reach_the_pdf_page` prints on はがき, L判, the はがき alias
and JIS B5 and reads the actual PDF MediaBox (283.46×419.53 and 252.28×360.00 pt).

Docs: docs/printing.md gains a Paper sizes section, docs/target-app-parity.md's
print row and revision history, and ROADMAP.md's progress log and revision
history, dated 2026-10-22; existing revision rows keep their dates.
2026-10-22 01:35:17 +09:00
FartmanAndBurps 755ca9e2a0 feat(print): add interactive preview positioning
Drag the visible image in the print preview using paper-scaled egui points.
Switch Center to manual without moving the grab point, allow signed Top/Left
offsets, and retain the shared preview/PDF layout and mirrored behavior.

Add regression coverage for negative PDF placement, native HiDPI dragging,
centering, clipping, scaling, fit, mirroring and invalid geometry.

Validation: 25 engine print tests, 19 file-dialog unit tests, four print-dialog
integration tests and the adversarial-command test pass. Formatting,
all-target clippy, desktop check/build and layer checks pass.
Three existing socket-binding tests are sandbox-blocked and excluded from
the successful print-suite rerun. GUI capture and wasm checks remain limited
by the environment.
2026-10-21 12:31:08 +01:00
jlangeandClaude Opus 5.5 f3ede6136b Print: the printable area turns with the paper (#7782)
#7847 added Portrait and Landscape to the Windows Print dialog. A turn took the
settings and the paper from file.print.page but kept the portrait printable
area, so Scale to Fit Media refused the turned sheet. It now takes the area
from the same answer, or drops it. The engine reads the driver's area through
settings_for_layout, the same turn print_windows makes, so a landscape layout
on portrait settings fits the landscape area.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 03:47:38 +02:00
WolfandClaude Opus 5.5 2f08860383 Print: Portrait and Landscape in the Print dialog on Windows
On Windows the Print dialog takes the paper and its orientation from the
printer driver, and had no way to change the orientation short of the
driver's own Print Settings… dialog. Photoshop has Layout buttons for it.
A print laid out landscape on portrait driver settings (from a script,
the CLI or another app) stopped with "the driver paper or orientation
differs from the print layout".

- The dialog has an Orientation row (Portrait, Landscape) under Print
  Settings…. It turns the driver settings through file.print.page and
  takes the paper from the driver again, so the paper and preview turn.
- file.print.page takes "orientation": "portrait|landscape" and returns
  the turned settings as printerSettings, with the page they give.
- print_windows turns the settings (the given ones or the printer's
  defaults) to the layout's orientation when the driver has the layout's
  paper the other way round; another paper is still refused.

Turning sets dmOrientation and its dmFields bit in the DEVMODE and keeps
every other byte, the driver's private settings included; the driver
validates the result as it does settings from Print Settings…. No new
UI strings: "Orientation", "Portrait" and "Landscape" are in every
catalog.

Tests: the turned settings (orientation set, all else kept, with and
without private driver bytes), when a paper counts as turned, an unknown
orientation refused before any printer is asked, the dialog's reading of
the driver paper and its error path, and, run by hand on Windows, a
real "Microsoft Print to PDF" driver turning for a landscape layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:46:41 +02:00
Diego Chagas 235e7578f3 Print through CUPS over IPP and the print portal, so File › Print works in the Flatpak (#2728) (#3017)
Main prints through craft-print, which runs `lp`; a Flatpak has no `lp`,
so File › Print fails there. This keeps craft-print as the route wherever
`lp` is on the path (and on Windows) and adds two more behind it:

- `photocraft-ipp`, a pure-Rust IPP client (CUPS-Get-Printers/Classes/
  Default, Print-Job over HTTP/1.1) that talks to CUPS over its socket or
  TCP; the Flatpak manifests grant --socket=cups for it. A `printServer`
  named in the request always takes this route. `file.print.printers`
  lists the queues.
- The XDG Print portal as the app's spooler (`Session::print_spooler`),
  for a sandbox without the CUPS socket or a system without a printer:
  the system print dialog, seeded with copies, paper and orientation.
  PHOTOCRAFT_PRINT_PORTAL=1 prefers it, =0 removes it.

A route that exists but fails (unknown printer, refused job) is an error;
only a missing route moves on. Results gain `backend` (lp, windows, ipp,
portal). docs/printing.md describes the routes.
2026-10-17 15:55:54 -06:00