pdfcraft/crates/platform
gyurix c933782039
Linux: "Use system setting" asks the desktop, not winit (#881)
winit reports no system theme on Linux — `ActiveEventLoop::system_theme` is
`None` there on every desktop — so `ThemePreference::System` never saw the
desktop's choice and silently fell back to whatever was on screen: PdfCraft
came up light on a dark desktop, and picking "Use system setting" after Dark
kept it dark. The default setting did not follow the system.

`pdfcraft-platform` now reads the XDG Desktop Portal's Settings interface off
the UI thread and the app follows the answer, including a change made while it
runs. The colour scheme is asked for under its GNOME schema name first, which
GNOME's and XFCE's portals both answer, then under the older freedesktop one,
which KDE answers. A desktop that answers neither leaves the user's own choice
alone, exactly as before.

Co-authored-by: GyuriX <gyurix@users.noreply.github.com>
2026-10-10 15:47:33 -04:00
..
src Linux: "Use system setting" asks the desktop, not winit (#881) 2026-10-10 15:47:33 -04:00
Cargo.toml Linux: "Use system setting" asks the desktop, not winit (#881) 2026-10-10 15:47:33 -04:00
README.md Platform: one save-staging helper for automation and the desktop app (#356) 2026-10-08 17:07:00 -04:00

README.md

pdfcraft-platform

Layer L7 holds operating-system services that both the desktop app (pdfcraft-ui-egui) and the automation tools (pdfcraft-automation) need. Those two crates sit on the same layer and can't depend on each other, so a helper they share lives here instead of being copied into each (xtask/src/layers.rs allows both edges). It uses only the standard library and has no UI dependencies.

staging creates the temporary file an atomic save writes before renaming it over the target. The file is opened with create_new, so anything already at the name (a file, a hard link, a symbolic link even when dangling, a folder) is skipped and never written through. On Windows a folder at the name fails with "access denied" rather than "already exists", and is skipped only when something is actually there. Names carry an unpredictable 64-bit suffix from staging_suffixes (the standard library's keyed hash, currently SipHash-1-3, keyed from the operating system's random source), which stops a name being planted in advance but is not a CSPRNG; fixed suffixes are only for tests. At most 16 names are tried, and then the save is refused. The target's name is cut to 128 bytes on a character boundary so the staging name fits every system's limit. Each caller keeps its own name form (.{name}.{suffix}.pdfcraft-tmp for automation, .{name}.pdfcraft-{suffix}.tmp for the desktop save). Writing, closing the file before the rename, renaming and removing the staging file on failure stay with the caller.

Synthetic tests pin both name forms, the 128-byte cut, the attempt limit and refusal when no name is left. The planted-file, link, folder and failed-rename tests stay with each caller, where they exercise the whole save.