9 Commits
Author SHA1 Message Date
c0cb78090b panic_hunt: count panics that Session::execute contains (#4982) (#5219)
Session::execute catches a command's panic and returns an ordinary Err (the
last-resort guard in jobs.rs), so the unwind never reached panic_hunt's own
catch_unwind and a panicking command counted as a pass.

The harness now installs a panic hook that counts every panic in the process,
including on rayon workers, and a run fails if the count moved. Runs are
serialised so a panic is charged to the run that caused it. No production
code changes.

Test: contained_panics_count_and_graceful_errors_do_not. A contained panic
fails the run and a graceful Err passes; the first assertion fails without
the hook. The full --ignored fuzz stays green, so no command panics today.

Co-authored-by: prekabreki <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 01:59:18 -04:00
prekabrekiandprekabreki 9829d7ea37 Duplicate Layer from the menu opens a dialog for the copy's name and destination document (#3348) (#3440)
Co-authored-by: prekabreki <[email protected]>
2026-10-11 23:02:59 -04:00
prekabrekiandprekabreki e762c784fb Keep transform controls with moved selected pixels (#3402) (#3436)
Co-authored-by: prekabreki <[email protected]>
2026-10-11 17:09:15 -04:00
prekabrekiandprekabreki f9e94aa535 Keep the Color panel selected when switching themes (#3371) (#3433)
* Keep the Color panel selected when switching themes (#3371)

* Scope Camera Raw color checks to its settings panel (#3371)

---------

Co-authored-by: prekabreki <[email protected]>
2026-10-11 17:02:38 -04:00
0423f74b50 Paint Bucket and Gradient keep alpha on a transparency-locked layer (#1104) (#1193)
composite_area already honours lock transparency, but paint_gradient and
bucket_fill(_src) always passed false, and paint.bucket / paint.gradient
dropped the flag target_surface returns. Thread it through, as Edit > Fill
and the brushes already do.

Co-authored-by: prekabreki <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 17:05:25 -04:00
2425431c78 layer.delete keeps a document's last layer (#1107) (#1189)
The single-layer path removed the layer with no guard, leaving a document
with no layers and no active layer. It now refuses with the same error as
the multi-select path; the edit is discarded, so nothing changes and no
history step is recorded.

Co-authored-by: prekabreki <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 17:05:20 -04:00
a32ba211c9 Clear, Cut and Image › Adjustments refuse a pixel-locked layer (#1103) (#1194)
* Clear, Cut and Image > Adjustments refuse a pixel-locked layer (#1103)

clear_area, destructive_adjust and auto_adjust took the layer's surface
directly. They now go through commands::paint_surface, which refuses a
pixel- or fully-locked layer with the same message painting uses.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* edit.cut: refuse a pixel-locked layer before filling the clipboard

copy() ran before clear_selected noticed the lock, so a refused Cut still
replaced the clipboard. Check the lock first (check_pixels_unlocked, shared
with paint_surface) and assert the clipboard is unchanged in the test.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: prekabreki <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-08 17:04:33 -04:00
e8850ac53a Filters respect layer locks; render filters and Fill Path refuse a pixel-locked layer (#1102) (#1195)
* Filters refuse a pixel-locked layer (#1102)

run_filter never consulted layer locks. It now refuses a pixel- or
fully-locked layer with the same message painting uses. Channel, Quick
Mask and mask targets are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Filters keep alpha under lock transparency; render filters and Fill Path refuse a pixel-locked layer (#1102)

- run_filter puts the layer's alpha back in the tiles a filter changed when
  transparency is locked (the same tile walk as restrict_to_color).
- Flame / Tree / Picture Frame take the surface through paint_surface.
- path.fill refuses a pixel- or fully-locked layer.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: prekabreki <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 16:38:59 -04:00
0d11e76fef Toolbar: the header chevron switches between one and two columns (#1197) (#1200)
* Toolbar: the header chevron switches between one and two columns (#1197)

The Pro theme's chevron was painted with a hover-only sense, so clicking it
did nothing. It now toggles Panels::toolbar_double (serde default, so older
state still loads); the toolbar is two columns when that is on or when one
column doesn't fit, and the chevron points left while two are shown.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Toolbar: the Pro two-column toolbar fills every row (#1197)

Rows were cut per tool group, so a group with an odd number of tools left
a half-empty row (Move, Eyedropper). Pro draws no group dividers, so its
two columns now flow across groups; the other themes keep their per-group
rows between dividers.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: prekabreki <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 16:19:26 -04:00