The swatches that now open the full Color Picker changed only on OK, so Photo Filter, B&W Tint,
Gradient Map stops (Properties and Image > Adjustments), the Content-Aware Fill and Select and Mask
overlays, Neon Glow and Save for Web lost the live preview main's popup had. The open picker now
previews its colour on the swatch every frame, Cancel (or OK unchanged) restores the exact opening
value (bit-exact for linear floats), and the Properties panel commits one history step when the
picker closes. A picker closed without OK or a preview changes nothing (a Gradient Map stop at a
PSD's 1229/4096 kept its location on Cancel).
With no document open, the options-bar popover's Color Picker refused OK ("no document open")
before reaching the tool-only path; it now sets the next shape's colour as on main.
A popover swatch the shape refused (a job holding the document) still joined Recently Used Colors;
it now joins only after the edit succeeds. Adds a CAF keys test for an open widget picker, and
fixes the ui-parity date and count the main merge set back.
Co-authored-by: SimoneRecchia <201361065+SimoneRecchia@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts resolved as unions of both sides: codecs re-exports (PngRows + TiffBands), smart_cmds source imports
(main's source_surface_from_buffer and cache API with #8571's svg_source_image_in/convert_svg_source; main's
duplicate rendering import dropped), io flat.rs test modules (#8536's banded TIFF tests and main's PNG ones),
menus/invoke.rs (#8571's smart SVG intercept and main's layer.selectUnderCursor), state.rs (#8311's
type_box_overflow and main's type_insertion_style), the canvas_geom test keeps the is_finite guard, docs
status lines keep both change lists, i18n catalogs keep both sides' rows (hi.tsv: main's wording where both
added the same string).
748 upstream commits: append-only conflicts (i18n, ui-parity, people.toml,
the tools module lists) keep both sides. Scorecard: 12 of 183 settings do
nothing; docs/ui-parity.md follows it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsCL5E2GM6hUabP9dmYAv
217 upstream commits. Upstream added a colour swatch (Select and Mask's
overlay colour): it now opens the Color Picker titled "Color Picker
(Overlay Color)". Content-Aware Fill and Select and Mask leave their keys
to an open Color Picker, as they did for the swatch popup it replaced
(test keys_wait_while_the_overlay_colour_picker_is_open).
docs/ui-parity.md keeps the scorecard's 12 of 182.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsCL5E2GM6hUabP9dmYAv
Main split the files this PR changes: transform_tool.rs into tools/transform_tool/ (begin,
commit, drag_modes, draw, pointer, tests), canvas.rs into canvas/ (display, tool_input,
transform_controls, transform_controls_tests, snap_ui), and transform_cmds.rs into
cmd/transform_cmds.rs + tests.rs. The PR's changes are carried into the new modules as they
were. One adaptation: rotate_dir on main takes the live gesture (#5405), so the shared box's
gesture is passed through a new live_gesture helper instead of the PR's `rotating` bool.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reference application marks a paragraph box that can't hold its text
with a black "+" inside an enlarged lower-right handle; nothing is drawn
below the box. The PR drew a red disc 0-9 px below the box at a fixed
screen offset, so on a rotated layer it came loose from the box, a click
on it either grabbed the corner handle or ended the edit, and its hover
card popped up while dragging that same corner to enlarge the box.
Now the lower-right handle grows to 11 px and carries the black "+",
centred on the transformed corner, and the whole enlarged handle grabs
that corner, also in a rotated view. The disc, the hover card (state, its
tooltip row in every catalog), the GPU pixel test and its pollster
dev-dependency are gone; detection (`TextLayout::overflows`) and the
`typeBoxOverflow` inspect flag stay. docs/ui-parity.md: the overflow row
no longer claims box threading, the Guides row the PR duplicated is
removed, and the history has one row in date order.
Tests: `an_overflowing_box_shows_a_plus_in_its_enlarged_lower_right_handle`
(upright and rotated box; fails on the PR head with a 7 px handle) and
`the_whole_enlarged_overflow_handle_grabs_in_a_rotated_view`.
Co-authored-by: VladimirPozdnyakov <49595925+VladimirPozdnyakov@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The font menu from #6526 (preview, filter bar, class list, favourite stars,
style expanders, format badges) now sits under the editable family field:
the field is the search, so the menu has no search box of its own. The list
keeps the viewport measured when the menu opens and shrinks to its message
when nothing matches, ending with the class list.
keys.rs takes main's split key handlers with this branch's changes: caret
moves and Cmd+A clear the pending typing font, and Cmd+Enter waits for the
IME. Explicit imports replace `use super::*` for the strict lints;
`with_target` is gone on main.
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Port visibility preference, choice registration, live panel style and canvas override. Keep current animated camera and toolbar exclusions. Relocate misplaced persistence regression to prefs tests; retain current parity score counts.
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Added Alt guide rotation in current ruler/tool-input modules and engine Move Guide, retaining click-versus-drag selection, deletion on either ruler, colors, ruler-origin units and snapping. Selection follows the new orientation/index after a successful turn; original guide-turn/deletion regressions retained.
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Kept current stronger Hand modifier zoom implementation including sticky modifiers, primary-release ownership, middle-button pan and Free Transform exclusions; retained the original approved zoom/pan/release regressions alongside newer guards.
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Ported hanging punctuation into current line placement and kerning modules, preserving forced breaks, bounded edge-tip row merging, justified-last-line behavior, area exclusions and independent Roman orientation shaping; kept PSD/engine/UI regression coverage.
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Registered adjustment presets in current dialog modules, preserving current editor dispatch, explicit PhotoCraft preset provenance, Custom matching and discrete preview/history regressions.
Integrate main 69b8fd9c1, retaining multi-channel selection and editing through extracted channel-panel, Move-pointer and tone-editor helpers. Adapt explicit imports and preserve progress-document histories.
CodeRabbit: removing the popover's inline eyedropper dropped the only test
of screen sampling from the shape Fill/Stroke controls. The sample now
waits in the Color Picker until OK, then sets the next shape's colours.
docs/ui-parity.md: the status line's preference count matches the
scorecard (12 of 182).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsCL5E2GM6hUabP9dmYAv
- The Stroke Color Picker on a shape whose stroke is off (none or 0 px)
previews the stroke its OK turns on, at the enabled width, even for the
colour it opened on (CodeRabbit).
- No Color's diagonal uses the theme's danger token, not a fixed red.
- docs/ui-parity.md: the history entry notes Recently Used Colors is a new
preference, so 12 of 182 do nothing (matching the row).
- The Fill/Stroke swatches clip their checker to the rounded corners, so
dark themes no longer show white specks there (#8741).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsCL5E2GM6hUabP9dmYAv
Integration batch 9 (#9775) raised the preference count to 181 and
added its own 2026-10-27 status lines and history rows to gaps.md and
ui-parity.md. Both sides are kept: the scorecard regenerates to 11 of
181 do nothing, the branch's entries say 181 and are dated 2026-10-27,
above main's 12-of-181 rows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream moved the touched modules (dialogs/, tools/, widgets/ split) and
added its own Gradient tab to the shape Fill/Stroke swatches. Resolved by
porting this branch's changes onto the new layout:
- widgets/color.rs: color_edit_button* open the full Color Picker dialog
(tests in widgets/color_button_tests.rs).
- tools/paint_picker.rs (was paint_picker.rs): the popover reuses
shape_paint_ui::PaintChange (plus OpenPicker) and upstream's
shape_gradient_ui Gradient tab instead of its own gradient preset list,
so gradients now also work for the next shape's defaults.
- shape_paint_ui::swatch draws the popover; shape_options and
vector_ui/options handle OpenPicker and Recently Used Colors.
- adjust_editors, caf_ui, file_ui call sites and tests moved to their
new files; i18n entries appended after upstream's.
- docs/scorecard.md regenerated (12 of 181 settings unread).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsCL5E2GM6hUabP9dmYAv
Picks up the export speed work (#9877) and the rest of main. Main's
prefs audit now counts 180 preferences, so the regenerated scorecard
reads 11 of 180 do nothing, and the branch's doc entries say 180 to
match; the 2026-10-25 history rows keep their 178.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CodeRabbit on #9775: the 12-of-181 count changed today, so ui-parity.md and gaps.md get the date in their status lines and a revision-history row, as AGENTS.md asks.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Conflicts with main's batch #9880:
- psd file.rs / layer.rs: #5287 (PSB by encoded size, RLE tables widened on
promotion) against #6583's lazy reader. Main's new widening and length code
read `.data`, which #6583 leaves empty while the bytes stay in the source;
it now goes through `encoded()` / `encoded_len()` (also the auto-merged
lines in `rle_widening`, `encoded_len` and `LayerRecord::write`), and the
lazy reader sets `write_as_psb: false`. New test
`a_lazy_psd_promotes_to_the_same_psb_as_an_eager_one`: a lazily read PSD
writes the same PSB bytes as an eager one; it fails with a `.data` read.
- direct_select.rs / vector_ui.rs: #9321's Type Path and #6353's hidden
Work Path both kept.
- io tests main.rs: both modules. scorecard.md regenerated (12 of 181);
ui-parity.md and gaps.md follow it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CodeRabbit on #9775: Place::AutoEditable puts type, shapes, pastes, placed files and frames above a group whose lock would refuse them; ui-parity.md's status line and checklist row said every new layer goes into an open active group.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CodeRabbit on #9775: FontLibrary::finish wrote a failed type.font.favorite to the status bar as plain information; it now sets status_error like the other status writes. The regenerated scorecard counts 12 of 179 preferences that do nothing; ui-parity.md and gaps.md still said 178.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Upstream split canvas.rs and lib.rs into modules and moved the dialogs
under dialogs/. The preview module moves with them
(dialogs/color_picker_preview.rs); its canvas hooks now sit in
canvas/display.rs and canvas/textures.rs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QvfaMyAX4i4PbKBMnvFj6
Main moved the engine commands into crates/engine/src/cmd/ and the
dialogs and panels into submodules. The PR's placement calls follow
them, and main's new insert sites (new_adjustment in adjust_params.rs,
Place in file_cmds/open.rs, shapes in vector_cmds/shape.rs) use
layer_place::insert_new like the PR's originals. The New Group dialog
moves to dialogs/new_group_ui.rs; the Layers panel flyout's New Group…
opens it.
Main's Session::precheck now also checks layer.new.group's and
layer.new.groupFromLayers' new params (name, color, mode, opacity,
position), so precheck_agrees_with_execute holds. Main had since added
"New Group…" to every catalog: the PR's duplicate rows are dropped.
Main's newer tests that made a layer with an open group active now
open the group last, as the PR did for the older ones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PR's follow-up commit appended the reworded entries instead of
replacing the first ones, so both versions were in the doc. Keeps the
"at least 53 pt tall" wording.
Co-authored-by: hectorviov <1501713+hectorviov@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While the Type tool's Color Picker (Text Color) or a gradient fill
layer's Color Picker (Stop Color) is open, the canvas shows the target
(the selected characters, every selected type layer, or the stop) in the
colour under the cursor, as Photoshop does. The preview runs the command
OK will run (type.setStyle / gradient.fill.stop) on a copy of the
document, so the session's document, revision and history are untouched:
Cancel only stops showing the copy, OK commits the previewed edit in one
history step. Canvas invalidation is limited to the target layers'
bounds, with a full refresh while they are empty.
Follows the existing preview pattern of the Solid Color, shape fill and
text style colour pickers. Refs #5530.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QvfaMyAX4i4PbKBMnvFj6
Integrate main 59cb4c49b, including egui 0.37, the rebuilt Histogram
panel, live Mixer Brush and smart-filter mask painting. Preserve selected
native components and captured mask/dialog targets through the merge,
with preview, replay, undo and mode/depth regressions.
commit_shortcut skipped the highlighted row and fell back to the first
match, so with the current family highlighted it applied a different
family than the menu showed. Both paths now share accept_row (exact name,
then the highlighted row, then the first). Also remove the blank line
that split the ui-parity revision-history table.
Graphics Adapter (performance.gpuAdapter) always took effect, but startup read it by its raw
JSON key, which the scorecard prefs audit can't see, so it was counted as a setting that does
nothing. read_gpu_adapter now deserialises the performance section into prefs::Performance, as
read_display_server already does. A malformed value elsewhere in the section falls back to
automatic, as the display server does.
Settings that do nothing: 12 -> 11 of 178. Scorecard regenerated; gaps G9, ui-parity and
target-app-parity updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>