Commit Graph
275 Commits
Author SHA1 Message Date
aiongg f32f882f3a Merge main into integration-10
# Conflicts:
#	apps/photocraft-web/src/web.rs
#	apps/photocraft/src/services.rs
#	crates/engine/src/file_cmds/tests.rs
#	crates/engine/src/float_cmds.rs
#	crates/engine/src/float_cmds/tests.rs
#	xtask/src/corpus.rs
#	xtask/src/corpus_pins.rs
#	xtask/src/main.rs
2026-10-21 21:56:26 +00:00
aiongg e4a413241a Merge PR #8004: Windows on ARM: auto picks DirectX 12 for Qualcomm graphics (#7537) 2026-10-21 21:56:21 +00:00
aiongg 7b81efddcb Merge PR #5436: IO: open .psd through the PSD reader, not codecs (#5258) 2026-10-21 21:56:21 +00:00
aiongg f3c20b9242 Merge PR #7626: Flatpak: a second launch hands its files to the running PhotoCraft over a Unix socket (#1540) 2026-10-21 21:56:10 +00:00
aiongg 419f6ef4c7 Merge PR #6910: Web: one press per tap, so menus open again on touch (#2095) 2026-10-21 21:55:49 +00:00
skylar taylor-barrickandGitHub 6d8cbac7dc Merge pull request #2945 from diegochagas/feat/xcf-read
Open GIMP XCF files: layers, groups, masks, blend modes, channels and selection
2026-10-21 14:35:32 -06:00
Diego Chagas ca18689304 Open GIMP XCF files: layers, groups, masks, modes, channels and selection (#1076)
PhotoCraft reads GIMP's .xcf (and .xcf.gz) files, read only, through a new
reader in photocraft-io written from the public XCF specification: versions
0 to 26, uncompressed, RLE and zlib tiles, 8/16/32-bit integer and
16/32/64-bit float precisions (linear precisions get a linear profile),
pixel layers at any position, groups by item path with pass-through,
layer masks applied or disabled, opacity, visibility, locks, colour tags,
the 2.10 and legacy blend modes mapped to Photoshop's (modes without an
equivalent open as Normal with a note), the ICC profile, resolution,
guides, the comment, extra channels and the saved selection; indexed
images open as RGB. Text, vector and link layers open as their pixels;
layer effects, paths and floating selections are reported.

Fixtures are written by GIMP 3.2 itself (scripts/xcf_fixtures.py), each
with GIMP's merged rendering as a PNG. In gamma-encoded blend and
composite spaces our composite matches GIMP within 0.5/255; GIMP's
linear-light default, its Clip to backdrop and its clamp-after-alpha
for unbounded modes are documented and measured in docs/xcf.md.
2026-10-21 16:57:22 -03:00
aiongg 54229918c9 Merge PR #7271: macOS: keep the bundle's Dock icon after the window opens 2026-10-21 18:15:07 +00:00
aiongg 94d28535d3 Merge PR #6464: Survive a lost window GPU device: draw nothing, save unsaved work for recovery, close (#3438, #1215) 2026-10-21 18:15:02 +00:00
aiongg 77557d75f1 Merge PR #8229: Integration batch: 8 PRs on main
# Conflicts:
#	crates/engine/src/layer_style.rs
#	crates/io/src/psd_export.rs
#	crates/io/src/smart_map.rs
#	docs/file-format-parity.md
2026-10-21 15:45:07 +00:00
Branch Sync 960d927a37 Merge remote-tracking branch 'refs/remotes/upstream/main' into HEAD 2026-10-21 11:18:25 -04:00
Branch Sync 643c9b7044 Merge remote-tracking branch 'refs/remotes/upstream/main' into HEAD 2026-10-21 11:15:30 -04:00
f5543e85fc Integration: merge main, resolve conflicts (#5407)
main added the GPU adapter strings (#1885) at the end of every
translation table, where this PR adds the Color Table strings. Both
blocks are kept.

Co-authored-by: abdul-karim-mia <97598943+abdul-karim-mia@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 11:23:09 +02:00
aiongg de03dd43f1 Merge PR #6861: CLI batch: skip shell-only Save and view steps inside played action sets (#6860) 2026-10-21 05:04:01 +00:00
Higgs32584andClaude Opus 5.5 576b7cdfcb Merge upstream main into fix/2095-android-menus
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 21:19:22 -04:00
Higgs32584andClaude Opus 5.5 c00045d7d9 Merge upstream/main into fix/7537-windows-arm-dx12
Resolve conflicts with #4's "Auto on Windows leaves Vulkan out when an
Intel adapter is present" (3c9c93ed) and #7813's adapter choice
(`configure` gained `wanted`):

- gpu_startup.rs: `intel_dx12_applied(.., vulkan_left_out)` from main and
  the patch's `dx12_default_applied` become one
  `dx12_default_applied(adapters, chosen, os, vulkan_left_out)` that
  returns the maker's name (Intel or Qualcomm). `vulkan_left_out` counts
  only for Intel, since only an Intel DXGI adapter makes
  `windows_auto_backends` drop Vulkan. `configure` keeps main's `wanted`
  parameter and Vulkan-free instance; the System Info note names the maker.
- Tests: keep both main's Intel instance test and the Qualcomm test,
  updated to the merged signature, plus one assertion that Vulkan being
  left out doesn't make a Qualcomm DX12 pick "the default".
- Module docs and docs/development.md: main's wording, with Qualcomm
  (Windows on ARM) added to the DX12 default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 20:55:06 -04:00
b484f45429 Integration: merge main, resolve conflicts (#5407)
apps/photocraft{,-web}: main added "cin" to OPEN_EXTS; kept it and the PR's
"act". apps/photocraft/src/services.rs: main gave File > Open one filter per
format (#6337) and checks with every_open_format_has_its_own_filter that the
filters cover OPEN_EXTS exactly, so "act" joins the Swatches filter.
i18n: both sides appended sections at the end of every catalog; kept both.

Co-authored-by: Abdul karim mia <97598943+abdul-karim-mia@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 01:49:54 +02:00
aiongg 92513627da Merge PR #5587: Preserve editable clipboard contents when native reads fail 2026-10-20 22:07:10 +00:00
aiongg 3a8ea8d9ad Integration: barrel check reads only the pen, not the global right button, for #6195
GetAsyncKeyState(VK_RBUTTON) reads the physical button system-wide: with swapped buttons a primary click read as right-down, and a right button held over another window counted too.
2026-10-20 22:07:10 +00:00
aiongg 77cd7118ee Merge PR #6195: fix(tablet): support stylus barrel button and brush resize on Windows (#5905, #5364) 2026-10-20 22:07:10 +00:00
Vikram Bhaskaran ff61346024 Open mislabeled .psd files from their raster signature.
PNG/JPEG/TIFF bytes named .psd still go through codecs, as on main and
in Photoshop. Only an unrecognized .psd keeps the PSD parse error.
2026-10-21 08:57:47 +11:00
Vikram Bhaskaran c0eb60dc84 Merge origin/main into fix/5258-psd-open.
Keep PSD routing in io. Use main's per-format Open filters, which
already include Photoshop.
2026-10-21 07:31:19 +11:00
aiongg db56aeb10a Merge PR #7813: Choose the graphics adapter on multi-GPU Linux machines (#1885)
# Conflicts:
#	apps/photocraft/src/gpu_startup.rs
#	crates/ui-egui/src/i18n/cs.tsv
#	crates/ui-egui/src/i18n/de.tsv
#	crates/ui-egui/src/i18n/el.tsv
#	crates/ui-egui/src/i18n/es.tsv
#	crates/ui-egui/src/i18n/fr.tsv
#	crates/ui-egui/src/i18n/hu.tsv
#	crates/ui-egui/src/i18n/id.tsv
#	crates/ui-egui/src/i18n/it.tsv
#	crates/ui-egui/src/i18n/ja.tsv
#	crates/ui-egui/src/i18n/ko.tsv
#	crates/ui-egui/src/i18n/nl.tsv
#	crates/ui-egui/src/i18n/pl.tsv
#	crates/ui-egui/src/i18n/pt-br.tsv
#	crates/ui-egui/src/i18n/ru.tsv
#	crates/ui-egui/src/i18n/sr.tsv
#	crates/ui-egui/src/i18n/tr.tsv
#	crates/ui-egui/src/i18n/uk.tsv
#	crates/ui-egui/src/i18n/vi.tsv
#	crates/ui-egui/src/i18n/zh-hans.tsv
#	crates/ui-egui/src/i18n/zh-hant.tsv
#	crates/ui-egui/src/prefs_ui.rs
2026-10-20 18:41:25 +00:00
aiongg ad2d420be2 Merge PR #7683: Web: start when the server already inflated the app's gzip part (Apache mod_mime_magic) (#7639) 2026-10-20 18:39:30 +00:00
aiongg 9ddc2805f0 Merge PR #6878: Windows: maximized window lets an auto-hidden taskbar show (#4845) 2026-10-20 18:39:29 +00:00
aiongg 60764172aa Merge PR #7217: GPU startup: Auto on Windows leaves Vulkan out when an Intel adapter is present (#4) 2026-10-20 18:39:29 +00:00
aiongg 1e2bea1060 Merge PR #6395: Windows: PhotoCraft starts without Windows.Data.Pdf.dll (#5884) 2026-10-20 18:39:29 +00:00
aiongg c247a34bb6 Merge PR #7892: Indexed GIF opens in Indexed Color with its colour table, as in Photoshop (#7886) 2026-10-20 18:39:28 +00:00
Guillem HermidaandGitHub 872748fb5b Codecs: save DDS textures, uncompressed or BC1–BC3, with optional mipmaps (#1327) (#5993)
DDS textures can now be saved, not just opened: uncompressed (BGRA, BGRX, L8, A8L8; lossless) or BC1/BC2/BC3 (DXT1/3/5) from a clean-room block encoder, with an optional box-filtered mip chain, in the legacy header. Save As and Save a Copy ask with DDS Options; scripts pass `ddsCompression`/`ddsMipmaps` (file commands, control `app.save`, RPC `doc.save`, MCP `doc_save`/`doc_export`), and the CLI takes `--dds-compression`/`--dds-mipmaps`. Targa and DDS answers travel together as `FormatChoices` through the Save As flow.

Review follow-ups:
- File › Save behind DDS or Targa Options records a plain Save with its answer, and replaying `file.save` applies it (#3531).
- The block encoder finds the principal axis from every channel, so a channel that varies on its own can't hide the others' variation.
- DDS joins the shared round-trip suite; the header is built before the output buffer is allocated.
- Enter on a focused Cancel in DDS, Targa or TIFF Options cancels instead of saving.
2026-10-20 11:02:39 -06:00
Higgs32584andClaude Opus 5.5 b19293d293 Windows on ARM: auto picks DirectX 12 for Qualcomm graphics (#7537)
On a Windows ARM64 PC the Qualcomm Vulkan driver lost the device
mid-session (Layer Style > Inner Shadow edits), the window's egui-wgpu
renderer panicked on the lost device and PhotoCraft exited. With the
backend set to DirectX 12 the reporter could not reproduce it.

`auto` already ranks DX12 before Vulkan for Intel on Windows. Extend that
rule to Qualcomm, matching both the id its Vulkan driver reports (0x5143)
and the one DXGI reports ("QCOM", 0x4D4F4351). System Info names the
maker in its note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 12:59:22 -04:00
Anim86 8fc62f55ab fix(tablet): support stylus barrel button and brush resize on Windows (#5905, #5364)
On Windows with Windows Ink (WM_POINTER), winit drops penFlags (PEN_FLAG_BARREL) and reports stylus contact as WindowEvent::Touch, which egui-winit maps exclusively to PointerButton::Primary. Additionally, Windows Ink does not update GetAsyncKeyState(VK_RBUTTON) when pressing the pen barrel button. Consequently, Alt + Barrel Button drag was recognized as Alt + Left Drag (triggering the eyedropper and painting strokes instead of brush resize), and right-clicks with the stylus were treated as left-clicks.

This commit resolves the issue by:
1. Adding a native Windows message hook (WH_GETMESSAGE) in crates/tablet/src/windows.rs calling GetPointerPenInfo to intercept PEN_FLAG_BARREL (0x00000001) and POINTER_FLAG_SECONDBUTTON.
2. Exposing 
ight_button_down in Services combining the pointer hook and GetAsyncKeyState(VK_RBUTTON).
3. Updating canvas.rs and paint_mouse.rs to prevent strokes_live and alt_eyedropper from hijacking the stylus gesture when the barrel button is held, and correctly routing resize events.
4. Adding tests asserting that Alt + stylus barrel drag resizes diameter horizontally and adjusts hardness vertically without triggering eyedropper or painting.
2026-10-20 11:17:58 +02:00
Korg1ch e92e5164a8 test(io): an indexed GIF keeps its table and transparent entry; malformed GIFs give no table (#7886) 2026-10-20 06:18:48 +03:00
jonathanwxh-cell 40130ae99e fix: reconcile PR with upstream changes 2026-10-20 11:16:40 +08:00
Ernie SmithandClaude Sonnet 5.5 53effe3c83 Review: keep the missing-adapter note, and forward the override in CPU mode
- A requested adapter that couldn't be used, followed by a software window
  adapter, lost its System Info note to the software-graphics message. Append
  instead of replacing.
- PHOTOCRAFT_GPU_ADAPTER only forces its own process when startup acts on it
  (Linux, outside CPU mode); in CPU mode it is ignored, so the launch may
  still go to the running window.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:31:57 -04:00
Ernie SmithandClaude Sonnet 5.5 0e97ac4ca8 Make adapter choice Linux-only everywhere, not just the dropdown
The Preferences row was Linux-only, but PHOTOCRAFT_GPU_ADAPTER and
performance.gpuAdapter were honoured on every platform, so Windows and macOS
could pick a non-default adapter without being tested for it. Ignore the
request off Linux (and in CPU mode, as before), and don't make a launch
standalone for a variable that is ignored there.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:19:51 -04:00
Ernie SmithandClaude Sonnet 5.5 2644d06081 Review: rustfmt, cap the env adapter name, docs in their own paragraph
- cargo fmt on the adapter selection and its launch code.
- PHOTOCRAFT_GPU_ADAPTER is capped at 256 characters like the saved preference.
- Put the multi-GPU paragraph in docs/development.md on its own instead of
  appending to the --safe-gpu paragraph, so the diff only adds lines.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:07:04 -04:00
Michael HigginsandGitHub fa9f11c7a7 Merge branch 'storytold:main' into fix/2095-android-menus 2026-10-19 14:31:10 -04:00
8bed609ef0 Flatpak on Wayland: say why a paste finds nothing, and how to paste anyway (#5031) (#5279)
In a Flatpak on Wayland, arboard can't open at all: the sandbox hides the
data-control protocol from it, and --socket=fallback-x11 gives no X server
while a compositor runs. Paste then reported "the clipboard holds no image"
even when it held one. Now the clipboard service reports that it had no
clipboard to read, and the paste shows a notice that explains it and gives
the XWayland command for this install.

Also adds my contributors/people.toml entry.


Claude-Session: https://claude.ai/code/session_01AbyXia7KGdFgbNjBeggY8J

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:20:29 -04:00
Ernie SmithandClaude Sonnet 5.5 0b6480cdc5 Address review: adapter override process, wasm build, saved-name warning
- PHOTOCRAFT_GPU_ADAPTER now counts as a per-process launch option, so a
  second launch with it set doesn't forward to the running window and drop it.
- Gate RenderState::available_adapters to native targets (it doesn't exist on
  wasm, which broke the web build).
- Share the adapter name matcher (engine prefs) between startup and
  Preferences, so a saved fragment like "nvidia" isn't flagged as missing when
  it matches a listed adapter.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 14:13:55 -04:00
Michael HigginsandGitHub cd781bb25f Merge branch 'storytold:main' into fix/2095-android-menus 2026-10-19 14:08:55 -04:00
Korg1chandGitHub 8c2cfdba6a fix(linux): keep crash-recovery autosaves in $XDG_STATE_HOME, out of the config folder (#6612) (#6941)
* fix(linux): keep crash-recovery autosaves in $XDG_STATE_HOME, out of the config folder (#6612)

* test(linux): cover the XDG state recovery folder (#6612)
2026-10-19 13:32:14 -04:00
Ernie SmithandClaude Sonnet 5.5 b892c0412e Choose the graphics adapter on multi-GPU Linux machines (#1885)
With the backend on auto, Linux installed no adapter selector, so wgpu took
the first discrete GPU the driver listed. On a machine with an eGPU, a
laptop dGPU and an iGPU that was not the one the user wanted.

- performance.gpuAdapter: a case-insensitive piece of the adapter's name
  (several words must all appear); empty is automatic.
- PHOTOCRAFT_GPU_ADAPTER overrides it for one launch.
- Preferences > Performance > Advanced > GPU adapter lists the adapters the
  instance found; a saved adapter that is absent stays listed, marked.
- A missing adapter, or one that can't present to the window, falls back to
  the automatic choice with a note in System Info. CPU mode ignores it.
- Shown on Linux only; tested on Linux only. Windows and macOS need their own
  work (the startup code honours the setting there, but it is untested).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:16:53 -04:00
Korg1ch af0857372b test(web): the boot module tells gzip from wasm the browser already inflated (#7639) 2026-10-19 12:37:55 +03:00
Korg1ch cb1b479452 fix(web): start the app when the server already inflated its gzip part (#7639) 2026-10-19 12:37:54 +03:00
Diego Chagas f2a487b088 Flatpak: a second launch hands its files to the running PhotoCraft over a Unix socket (#1540)
#3755's hand-off listens on a loopback port, and every `flatpak run` gets
its own network namespace, so inside the sandbox the second launch could
never reach the first and opened a separate window. When FLATPAK_ID and
XDG_RUNTIME_DIR are set the primary now listens on
$XDG_RUNTIME_DIR/app/<app id>/instance.sock (0600), a directory every
sandbox of the app shares, and records "socket" instead of "port" in
instance.json. The lock, token, client cap, deadlines and reply are
unchanged; a crashed primary's socket file is unlinked under the lock,
and shutdown removes the socket.
2026-10-19 00:19:00 -03:00
Higgs32584 ac5611bc80 Merge remote-tracking branch 'upstream/main' into fix/5884-delay-load-windows-data-pdf 2026-10-18 18:22:11 -04:00
00xJ0 4615a8bc26 Survive a lost window GPU device: draw nothing, save unsaved work for recovery, close (#3438, #1215)
When the window's own wgpu device was lost (a driver reset, e.g. after sleep), egui-wgpu could
not draw another frame: a frame with shapes panicked inside it ("Failed to create staging buffer
for index data", #1215, exit 101, unsaved work lost), and a frozen window's close button opened
an unsaved-changes prompt nobody could see (#3438). The #243 fallback only covered the canvas.

- DeviceHealth::device_lost (wgpu reported the loss, not a recorded fault) and ::probe (a
  non-blocking poll that keeps running after a recorded fault).
- RecoveryStore::flush: finish queued autosaves and wait for them.
- gpu_status::check_window, at the end of every frame: once the window's device is lost the
  frame draws nothing; the first time every unsaved document is written to crash recovery
  (Services::flush_autosaves) and the app closes without asking. The next launch reopens them.
- The app watches the window device on the CPU canvas too; ui.gpu.simulateLoss {destroy: true}
  destroys the real device to drive the path.

Verified on an RX 6900 XT, Vulkan and DX12: destroying the device in the running app exited 101
with the egui-wgpu panic before, and now exits 0 with the document recovered on the next launch.
2026-10-18 12:53:48 -07:00
aionggandGitHub 4df773e966 Merge pull request #7405 from aiongg/next
Integration batch: 19 PRs on main
2026-10-18 11:09:40 -04:00
5b087699be Tests: fix the flaky file-lock tests and the occasional portal_save hang (#7418)
The rotation and instance-log tests in logging.rs, and two app_dirs migration-lock tests, drop a
flock and check straight away that it is free. A child that another test spawns at that moment
holds a copy of every open descriptor until its exec, the lock included, so the check sometimes
saw it still held (about 6 failures in 15 runs of the app's test binary). Tests that spawn
children (the portal mock's dbus-daemon, the display-profile helper test) now hold CHILD_SPAWNS
for reading while they spawn, and the lock tests hold it for writing.

The portal mock made its message stream inside its thread; a stream only gets messages that
arrive after it exists, so a SaveFile sent before the thread got going was lost and the test
waited forever (about 1 run in 25). The stream is now made before the thread starts.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:29:07 -04:00
aiongg 9692eea083 Merge PR #6346: File › Open: a file type filter per format (fixes #6337) 2026-10-18 14:18:59 +00:00