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
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
Main's smart-object cache handling in edit.transform (take_caches /
restore_unrendered) now covers every transformed layer; the params doc
keeps both the layers field and main's bicubic variants.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Delete the coverage tests, the per-language parity checks and the tests
of one language's exact wording. Catalog integrity, placeholder and
plural-form checks stay, as do the engine tests (locale resolution,
plural rules, fallback, language scoping, drawing in a language); those
compare against tr() or the plural rule rather than catalog wording.
Docs describe the report instead of a failing test.
Conflicts:
- vector_ui.rs: main gave egui's shape picker a hex field and a screen
colour button; this branch replaces that picker with the popover, whose
Color Picker has both, so the popover version is kept.
- vector_paint_tests.rs: main's zero-width stroke tests are kept; its two
hex tests now type and paste into the Color Picker the popover opens
(the test harness draws dialogs, as the app does).
- i18n catalogs: both sides' new strings kept; fr and ru keep main's
translations of Color Picker, Solid Color and Tint Color.
- paint_picker.rs uses photocraft_color::convert::hsb_to_rgb, which
replaced color_picker_ui::hsv_to_rgb on main.
- docs: both sides' rows and revision entries kept; scorecard regenerated.
The shape Fill and Stroke swatches (options bar and Properties) opened egui's
built-in picker, which only has RGBA fields and no hex. They now open
Photoshop's popover: No Color, Solid Color, Gradient and Pattern along the
top, the Color Picker button at the top right, Recently Used Colors and the
swatch library's folders. Gradient applies a gradient preset to the selected
shape; Pattern is shown but off, since shapes don't render pattern paint yet.
The Color Picker button opens the full Color Picker dialog (HSB, RGB, Lab,
CMYK, hex, eyedropper) titled Color Picker (Fill Color) / (Stroke Color),
with a live canvas preview; OK is one undo step (shape_fill_ui::open_paint).
Every other colour swatch built on widgets::color_edit_button* (Photo
Filter, Black & White tint, Gradient Map stop, Content-Aware Fill overlay,
Filter Gallery glow, Save for Web colour table) now opens the same Color
Picker dialog instead of egui's picker; OK hands the colour back to the
swatch through color_picker_ui::widget_tick.
Recently Used Colors are kept in Preferences::recent_colors (newest first,
15), filled by the Color Picker's OK and by popover picks.
Retain upstream contributor entries and Ratul’s original entry while
refreshing the UI scale presets branch against current main. Preserve
all scale presets, catalog labels, tests, documentation and coauthor history.
Validation: 5,290 engine/UI tests passed, 32 ignored; fmt, Clippy, layers,
wasm, scorecard generation/check and panic_hunt passed.
With several layers selected, Ctrl/Cmd+T framed and transformed only the
active layer, whatever its kind: a pixel layer moved while a type layer
beside it stayed put (or the other way round).
Engine: `edit.transform` takes `layers` and, given no `layer`, moves the
selected layers that no selected group carries, leaving out the Background,
as Photoshop does. One transform, one history step; every layer is priced
and lock-checked before any is built. Transform Again repeats on the
selection; Transform Again on a Copy keeps the active layer's frame.
UI: the box frames all of them (`begin_several`) and its preview is their
composite with styles reaching past the frame, rebuilt when an edit made
while it is open changes how they look (children of a moving group and
styles of enclosing groups included). Selected pixels are lifted per pixel
layer. The Move tool's shared Show Transform Controls frame gets handles.
Warp is greyed for several layers, and so are Distort and Perspective
while editable type is among them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T48KpM3QwGvfQxtZ1icCRq
Preserve main’s contributor entries and Auto scaling documentation while
retaining the intermediate fixed presets and their existing tests.
Add the four labels to the Hungarian, Serbian, Turkish, and Vietnamese
catalogs. Adopt #3396’s UI-217-9 note and UI parity/gap updates, then
regenerate the scorecard.
Co-authored-by: kartik8dwivedi <codewithme.kartik@gmail.com>
* Linux: a virtual keyboard claiming BTN_TOOL_PEN no longer sends the window through Xwayland (#5284)
On Wayland the app opens its window through Xwayland when a pen is attached
(#639), and it took any input device whose key bitmap has BTN_TOOL_PEN for a
pen. A virtual keyboard made with uinput (RustDesk's, for one) claims every
key code, that one included, so the window went through Xwayland on machines
with no pen at all. On a fractionally scaled desktop (GNOME 46 at 125%) the
X11 window is drawn at the logical size and upscaled by the compositor, so
the UI came out blurred even though Auto UI Scale already followed the
system's 1.25 (#1237): native Wayland, where winit negotiates
wp_fractional_scale_v1 and renders at the physical 3840 px, was never used.
A pen now also needs ABS_X and ABS_Y in its absolute-axis bitmap, as
libinput asks of a tablet tool; a keyboard has no axes. Regression tests
with the virtual keyboard's own bitmaps, a pen beside it, and a pen display.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Docs: on a fractionally scaled Wayland desktop, Xwayland is blurred and native Wayland has no file drops (#5284)
Say where the trade-off is: a native Wayland window is sharp at 125%,
150% and 175% but takes no dropped files (#386); an Xwayland window takes
drops and pen input (#639) but is enlarged by the compositor. List the ways
to open through Xwayland and what counts as a pen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
When appearance mode was toggled between dark and light with default
settings, PhotoCraft switched from Pro Medium (Pro layout) to Studio Light
(Studio layout), altering the UI and displaying a Fit button in the status
bar.
Now that the Photoshop Pro light brightness levels exist (#2661), default
the saved light theme to Pro Light so the Pro interface layout and status
bar are preserved when toggling appearance. Also map the "light" alias to
Pro Light and list the Pro options first under Light Theme preferences.
Fixes#5016.
A translated label beside a fixed-width control could run over its neighbours: the Layers
Lock/Fill row guarded only the redundant "Lock:" caption, so "Fill:" ("Заливка:" in Russian,
longer still as pt-br "Preenchimento:" / fr "Remplissage :") overlapped the lock icons.
Rather than a per-row fit check, add the one shared primitive for fixed chrome:
`widgets::elided_label(ui, text, max_w)` lays the text out no wider than its room, cuts it with
'…' and puts the full string on hover (built on the existing `tab_strip::elided`). The
Opacity/Fill scrub labels now elide to the room beside their field, so any translation shrinks
instead of overlapping, in every locale.
Documented the rule in docs/ui-design.md: wrap by default; beside a fixed control, elide; a
redundant caption may drop on a narrow dock (the lock icons carry the meaning).
Test: widgets::tests::elided_label_never_exceeds_its_room. Full photocraft-ui-egui suite: 2077
pass; fmt and clippy clean.
Load Work Path, saved path and layer path thumbnails as selections on
Ctrl/Cmd-click. Support Shift to add, Alt to subtract and Shift+Alt to
intersect, without changing the selected path or treating the click as
Save Path. Clicking the row name keeps its existing selection behavior.
Render uncached shape transparency instead of selecting the entire canvas.
Add regression tests for thumbnail hit testing, active-layer preservation,
selection combinations, undo/redo and 8/16/32-bit uncached shapes.
Co-authored-by: kotulsky <7805437+kotulsky@users.noreply.github.com>
* fix(ui): respect native desktop scale under Auto UI scaling (#1278)
* UI scale: drop the now-unused monitor size, update docs and scorecard
Merge main; Auto no longer reads the monitor size, so remove the parameter and its
computation, simplify the test, and update ui-design.md and UI-217-9 to match.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Mirror the shell for right-to-left UI languages (DIST-220-4)
Arabic, Hebrew, Persian and Urdu read right to left, but the window's
chrome was hard-wired left to right, so an RTL catalog (#2505) would
put Arabic labels into a left-to-right layout.
The reading direction now follows the language code
(i18n::dir_for_code: ar, ckb, dv, fa, he, ps, sd, ug, ur, yi), so a
catalog needs no extra setting and the LANGUAGES rows are unchanged.
In a right-to-left language the shell mirrors:
- the menu bar starts at the right with File; menus open under their
title's right edge, and the arrow keys step through them in screen
order
- the toolbox docks on the right, the panel dock and its rail on the
left; tool flyouts open towards the canvas and their corner marks
and the header chevrons follow
- the title, options and status bars read from the right, with the
workspace controls and the Fit/progress group at the left end; the
title and window-drag gap use the free span between them
New module direction.rs holds the helpers (start_panel/end_panel,
row/trailing layouts, horizontal_centered, the popup alignment). Left
to right, every change lays out as before.
No RTL catalog ships yet, so PHOTOCRAFT_UI_DIRECTION=rtl forces the
mirrored layout for review (read once, native only). Panel interiors,
dialogs, menu rows, submenus and document tabs stay left to right, and
egui still draws UI labels without Arabic shaping or bidi reordering;
docs/localization.md and the parity docs say so.
Adds Lucide's chevron-left (the status bar's info menu arrow points
left in RTL; Timeline's Previous frame button asked for it too and drew
the fallback square).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Localization docs: egui shapes Arabic words; what's missing is a font and bidi word order
egui 0.36 shapes right-to-left runs with HarfRust, so letters join within
a word. The gaps are an Arabic fallback font in the UI and paragraph bidi
(words are placed left to right; emilk/egui#8576, #8577).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: MathMattTech <334629259+MathMattTech@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Rulers: clip tick marks and labels outside the origin corner
* Rulers test: set ViewXform's new aspect field after merging main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Two Studio-layout themes for KDE Plasma desktops: original colour values
chosen to sit close to Breeze's cool blue-grey surfaces and blue accent
(and its 5 px radius) so the app blends into a Plasma desktop, without
copying Breeze's colour schemes. Text readability comes first.
- theme.rs: ThemeKind::BreezeLight / BreezeDark. Every text colour (text,
secondary, faint, accent, danger, warning) holds 4.5:1 on every surface
and on hovered, pressed and selected states; the primary button is a
deeper blue that takes white text and stays above 4.5:1 while it
darkens on hover and press. Breeze's own inactive text and link blue
are only about 2.8:1 on its light surfaces, so ours are darker. The
close button goes red on hover.
- prefs: Theme/LightTheme::BreezeLight ("breezeLight") and
Theme/DarkTheme::BreezeDark ("breezeDark"): Preferences > Interface,
`prefs.set`.
- Window > Theme > Breeze Light/Dark Theme (`window.theme.breezeLight`,
`window.theme.breezeDark`) and `ui.set {"theme": ...}` (aliases:
breeze, kde, plasma for the light one; ...dark for the dark one).
- i18n: the four new labels in all 16 catalogs.
- docs/ui-design.md and ATTRIBUTION.md (original work, credits Breeze as
the inspiration; Breeze's schemes are LGPL-2.0-or-later and none of
their values, files or code are copied).
- Tests: names/aliases, surface order and blue-grey character, the
contrast matrix for both themes, and the preference/mode selection.
* Expand arithmetic expressions across numeric inputs
* Test arithmetic and scientific notation in indexed color counts
* Drop the numeric_fields example (it wrote PNGs to /tmp; the widget tests cover the behaviour)
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* feat(ui): follow system appearance with a System theme
Follow the OS appearance through the existing egui input while retaining System as the saved theme choice. Apply the resolved palette to both egui styles and custom surfaces, and keep document surround settings independent.
Cover launch and live transitions, persistence, manual themes, menu checks, the Interface picker and Home contrast. Validate engine/UI suites, adversarial commands, wasm, layering, parity and the AutoReview gate. Strict Clippy reports pre-existing findings documented in the PR.
Refs: storytold/photocraft#2074
* Keep the document surround on the displayed theme in Sync with system (drop the dark-surround pinning)
---------
Co-authored-by: coygeek <coygeek@users.noreply.github.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Appearance modes: sync with system, separate dark and light themes
* Appearance button cycles Auto, Light, Dark
* Appearance: default stays Dark, follow the portal signal instead of polling, split out the Preferences resize
* Preferences: size both appearance cards for the five dark themes
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Toolbar: Studio themes draw large round colour chips with Switch Colors right below
* Toolbar: round chips keep Default Colors, follow Tokens::round_chips, lie side by side in two columns
* Theme: Solarized Dark and Adwaita use the Studio round colour chips
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Brush preset chip: draw the tip preview in the icon colour on light themes
The options-bar chip always painted the round tip white, which nearly vanished on Studio
Light's chrome (246 gray) and disappears entirely on a white header bar. Dark themes keep
Photoshop's white tip; light themes use their icon token.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Add Adwaita and Adwaita Dark themes
Two opt-in themes that put the Studio layout in GNOME's libadwaita palette, so PhotoCraft
sits with the rest of a GNOME desktop: header bar, sidebar, card and view colours, the
GNOME blue accent (#3584e4), destructive and warning colours, 6 / 9 / 12 px radii, and a
neutral (not red) close button as in GNOME's title bars. The default theme is unchanged.
Wired through ThemeKind, the interface.theme preference (adwaita, adwaitaDark), Window ›
Theme and the control channel, with menu and preference labels in every complete-menus
language ("Adwaita" kept as the proper name). A test holds both themes to WCAG contrast:
7:1 for text and 4.5:1 for dim text on every surface that carries labels.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* i18n: translate the Adwaita theme names in Dutch and Ukrainian
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
As in Photoshop CC 2019 and later, dragging an edge handle now scales both axes by the same
factor about the middle of the box (Alt: about the reference point), and Shift stretches the
one axis. Use Legacy Free Transform restores the old behaviour for edges as well as corners.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Windows and Linux the System title bar checkbox now carries the existing "Applies at next
launch." note, since saving it does not change the current window. Fixes#1661.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* type: transform editable text with temporary Ctrl/Cmd handles
* type: cover temporary transforms, editable files and preview costs
* docs: describe temporary Type transforms and automation
* type: release temporary previews immediately when gestures end
* test: benchmark the active 24 MP Type document
Auto forced at least 200% on any 4K monitor, overriding a fractional
system scale such as 125% or 150%, so Linux users on 4K got either
100% or 200% and nothing between. Auto now follows whatever scale the
system reports and uses the 200% fallback only when the system reports
no scaling (100%), which is the case #225 was fixing.
Claude-Session: https://claude.ai/code/session_01QcbChgBDVrdhjfsFA5D9nt
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Windows and Linux: one title bar with the app icon, like Photoshop
The window had the OS title bar stacked above PhotoCraft's own top bar. On
Windows and Linux the window now has no OS decorations and the top bar is
the title bar, as in VectorCraft and Photoshop on Windows:
- the app icon (brand.rs) leads the bar, before the menus;
- Minimize, Maximize/Restore and Close sit flush in the top-right corner
(Close turns red on hover; it runs File > Exit, so unsaved work is asked
about first);
- the free gap between the menus and the controls still drags the window
and a double-click there maximizes it;
- invisible 5 pt edges (12 pt corners) resize the window.
The right-hand group gets its own rect between the menus and the caption
buttons (egui's MenuBar takes the whole row, so it used to be laid out from
past the bar's end). Narrow windows drop what is also in a menu before
anything overlaps: Discord, then the theme toggle, then search, then the
workspace switcher narrows. macOS keeps its traffic lights.
New theme tokens caption_close / caption_close_text, Minimize / Maximize /
Restore in all 12 catalogs, and a --custom-titlebar flag for the snapshot
example.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Long right-click menus scroll inside the window instead of running off it
widgets::menu_scroll caps a context menu at the visible window height
(clear of a taskbar a too-tall window runs under, #315). egui moves the
popup up to fit, and it scrolls only when it is taller than the window.
Used by the Layers, canvas tool, Channels, Paths and document-tab menus;
the menu bar's menus already scroll (menu_nav::level).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* ⌘⌥⌃-click on the canvas selects the topmost layer under the pointer
With any tool, ⌘⌥⌃-click runs `layer.pickAt` at the pointer (the topmost
visible layer with pixels there becomes the selected layer) without
switching to the Move tool; the press, drag and release are swallowed so the
active tool never paints or draws. It runs before the ⌃⌥ brush-resize
gesture, which the same keys would otherwise trigger.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* quick_pick: document the macOS-only gesture, report a failed pick as an error
Windows and Linux never report mac_cmd, so the gesture is a documented no-op there and
Ctrl+Alt keeps resizing the brush. Tests cover both, plus a failed pick.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Jason Short <3344856+jason4short@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Apply the Interface UI Font Size preference
* Regenerate the scorecard after rebase (58 unread settings); drop the before/after screenshots
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>