Commit Graph

1103 Commits

Author SHA1 Message Date
bflatastic 2139c4d661 Merge #558: Fix #550: an SVG of chosen artboards holds only their art
# Conflicts:
#	ROADMAP.md
2026-10-09 01:45:04 +07:00
BFlat 179a87d0a6
Merge pull request: land #557 (fix #525)
Land #557 (fix #525: Image Trace of a large photo no longer crashes)
2026-10-09 01:42:04 +07:00
bflatastic b832599a47 Fix #550: an SVG of chosen artboards holds only their art
Exporting one artboard of many to SVG wrote the whole document's art into
that artboard's file, the other artboards' art outside its viewBox: an
editor opening it showed every artboard's art. A file for an artboard
named in the export (Use Artboards with a range or All, Export for
Screens) now holds the objects over that artboard only, at any depth of
layers, as DXF's crop leaves them; objects reaching into it stay whole
and a clipping layer keeps all of its objects. An SVG with no artboard
named (Save As) still holds the whole document.

Part of #546: Export As with a range writes the chosen artboard alone in
SVG, DXF, PDF and PNG, each file with that artboard's art (tested from
the dialogs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:38:38 +07:00
bflatastic d7b4d85d3c Merge #557: Fix #525: Image Trace of a large photo no longer crashes the app
# Conflicts:
#	ROADMAP.md
2026-10-09 01:35:31 +07:00
BFlat af7a5239be
Merge pull request #556: Release: VectorCraft v0.7.0
Release: VectorCraft v0.7.0
2026-10-09 01:18:16 +07:00
bflatastic 06242cd3ab Fix #525: Image Trace of a large photo no longer crashes the app
Tracing a 2048 x 2048 photo with High Fidelity Photo made 733,000 paths
and 7.8 million anchors. The selected result's outlines and anchor
squares then made an egui mesh of 1.8 GB, over the GPU's largest buffer:
wgpu panicked while painting and the app quit (or ran out of memory
first, at 6.4 GB).

- Canvas: a selection with more than 100,000 anchors shows its bounds
  instead of every outline and anchor, and the hover highlight skips
  such an object. The Contextual Task Bar and that outline read the
  selection's bounds from a per-revision cache (VectorcraftApp::
  selection_bounds): a selected trace drew a frame in 20 ms, not 170.
- Image Trace: the colour layers are traced in parallel (26 s to 1.9 s
  for that photo; the web traces them in turn). trace_within stops once
  the paths pass an anchor budget; imageTrace.make allows two million
  and otherwise reports the trace as too complex, with what to change.
  Images over 64 megapixels are refused from their header, before they
  are decoded.
- The trace crate's messages are translated (es, it) and scanned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:18:03 +07:00
bflatastic c3279f1bcf Release: VectorCraft v0.7.0
For users, since 0.6.0:
- Linux: no more startup crash on desktops whose compositor runs on another
  GPU (#502, #551); the window renders on the desktop's GPU and retries
  the next one instead of crashing.
- Windows: rendering through DirectX 12 first, fixing the black flicker on
  Intel GPUs (#545).
- Italian interface (#514).
- macOS: the menus live in the system menu bar.
- Panels, panel groups and the Tools panel undock into floating panels (#495).
- Live Corners on any path's corners: stars, polygons, pen paths (#511).
- Drawing tools snap to Smart Guides as the Selection tool does (#506).
- Pen: Cmd/Ctrl edits the path being drawn, Alt reshapes segments, drags
  out of the first anchor always close (#494, #501); Convert buttons for
  whole paths (#504).
- Right-click a ruler to change the document's units; the Control bar's
  Transform link opens the Transform panel.
- Object > Image Trace > Make traces with the Default preset (#543).
- Edit menu Select All, Cut, Copy and Paste act on a focused field (#516).
- Japanese UI: new type starts top-to-top with em box centre alignment (#432).
- PDF/.ai import keeps type strokes, wrapped lines and layer order (#508);
  EPS import fixes (#498, #505).
- macOS 27: only file URLs are opened (#433); Linux: the Paste menu no
  longer freezes on an unresponsive clipboard owner (#510).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:16:08 +07:00
BFlat 4f07bd93b0
Merge pull request #553: land #533, #548, #549, #552
Land #533, #548, #549, #552 with review fixes
2026-10-09 01:08:30 +07:00
bflatastic 086d6287be Merge #552: Fix #543: Object › Image Trace › Make traces with the Default preset
# Conflicts:
#	ROADMAP.md
2026-10-09 01:03:27 +07:00
bflatastic 0e6a47e72d Control bar: Italian for the Transform link's tooltip
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:03:03 +07:00
bflatastic f8004250fb Fix #543: Object › Image Trace › Make traces with the Default preset
Make… and Make and Expand… opened the generic parameter form, whose
preset was a text box holding a preset's name (Black and White Logo,
6 Colors), so the other presets looked missing. As in Illustrator, Make
and Make and Expand now trace at once with the Default preset, as the
Control bar's Image Trace button does; the button's arrow and the Image
Trace panel's Preset list choose among the 12 presets. The catalogs drop
the two "…" labels; Czech gets Make and Expand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:01:02 +07:00
bflatastic 03288f34dc Merge #549: Fix #545: Windows renders through DX12 before Vulkan
# Conflicts:
#	ROADMAP.md
2026-10-09 00:58:47 +07:00
bflatastic aa4fa48751 Merge #548: Part of #516: the in-window menus' Select All, Cut, Copy and Paste act on a focused field
# Conflicts:
#	ROADMAP.md
2026-10-09 00:58:46 +07:00
bflatastic 165db95dd4 Merge #533: Control bar: Transform link opens the Transform panel; reference point locator redrawn 2026-10-09 00:58:40 +07:00
bflatastic ac043129c8 Fix #545: Windows renders through DX12 before Vulkan
Windows lists each GPU under both backends, and Vulkan came first. On an
Intel GPU its driver made the whole window flicker black while the
pointer moved; the same machine was fine with WGPU_BACKEND=dx12 or gl.
adapter_order now ranks a GPU's DX12 adapter before its Vulkan one, after
the power preference, so the GPU chosen doesn't change, only how it is
driven. Vulkan stays the fallback (a failed DX12 start restarts on it)
and WGPU_BACKEND=vulkan still picks it. Elsewhere there is no DX12
adapter, so nothing changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:56:49 +07:00
bflatastic 8e753d746e Part of #516: the in-window menus' Select All, Cut, Copy and Paste act on a focused field
The clipboard keys already went to a focused text field, but on Windows,
Linux and the web the press that opens a menu takes the keyboard from the
field, so Edit > Copy (and Cut, Paste, Select > All) acted on the art.
The menu bar now keeps the field that had the keyboard, and its
selection, while the menus are open; those four commands go to it as the
events their keys send, the frame after the click that chose them, and
give it the keyboard back. Everything else, and those commands with no
field, run as before. The macOS menu bar shares the same helpers.

Tests: Copy, Cut and Paste events in the W field and the Color panel's
hex field edit the text, never the art; Select > All, Edit > Copy and
Edit > Paste clicked in the in-window menus act on the field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:51:02 +07:00
BFlat 85dcb28e41
Merge pull request #547: land #542, #523, #528, #527, #538, #529
Land #542, #523, #528, #527, #538, #529 with review fixes
2026-10-09 00:48:38 +07:00
bflatastic 971b0bb95e Merge #529: Fix #506: drawing tools snap to Smart Guides as the Selection tool does
# Conflicts:
#	ROADMAP.md
2026-10-09 00:44:46 +07:00
bflatastic 01c9be7d35 Part of #511: Italian rows for the Live Corners messages on any path
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:44:29 +07:00
bflatastic 7248c6aeec Merge #538: Fix #511: Live Corners on any path's corners (stars, polygons, pen paths)
# Conflicts:
#	ROADMAP.md
2026-10-09 00:44:29 +07:00
bflatastic 6efe9df3e8 Type (#432): the language test keeps its frames in English
The drawing language is process-wide, so a Japanese frame translated the
tests running beside it (Appearance, Attributes, menus). The test now
checks that each frame hands the engine its language without leaving
English.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:44:10 +07:00
bflatastic 7a270c8deb Merge #527: Type (#432): new type in a Japanese interface starts top-to-top with em box centre alignment
# Conflicts:
#	ROADMAP.md
2026-10-09 00:44:10 +07:00
bflatastic 5d695dcb80 Merge #523: Fix #433: open only file URLs handed to the app (macOS 27) 2026-10-09 00:43:58 +07:00
bflatastic cb6e996243 Merge #542: Clippy: use as_chunks for constant-size chunks (Rust 1.98) 2026-10-09 00:43:57 +07:00
bflatastic d9544d8f87 UI: the ruler unit menu in the ROADMAP; its test names the PR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:43:50 +07:00
bflatastic e28d9222e8 Merge #528: UI: right-click a ruler to swap the document units 2026-10-09 00:43:49 +07:00
Michael Gieson c21f783286 Clippy: use as_chunks for constant-size chunks (Rust 1.98)
Rust 1.98's clippy adds `chunks_exact_to_as_chunks`, which `-D warnings`
turns into an error, so `cargo xtask ci` fails on main with the current
stable toolchain. The EPS stencil-mask loop and the cursor rasterizer
(and two cursor tests) now use `as_chunks`, which yields fixed-size
arrays; like `chunks_exact`, it skips an incomplete last chunk, so
nothing changes in behaviour.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 12:57:16 -04:00
BFlat 843f46108c
Merge pull request #509 from storytold/feat/macos-menu-bar
macOS: the menus live in the system menu bar, settings in the VectorCraft menu
2026-10-08 23:48:25 +07:00
bflatastic ab65474044 macOS: the menus live in the system menu bar, settings in the VectorCraft menu
On macOS the menus are in the system menu bar, laid out as a Mac app's (Illustrator on the Mac as
the reference), and the app settings sit in the VectorCraft menu: About, Settings ▸ (one item per
Preferences page, General… ⌘K), Language ▸, Appearance ▸ (UI brightness), Services, Hide
VectorCraft ⌃⌘H (⌘H stays View › Hide Edges), Hide Others ⌥⌘H, Show All and Quit ⌘Q (the app's own
quit, so unsaved documents are asked about); they leave Edit and Help. Window gets Minimize ⌃⌘M,
Zoom and Bring All to Front; Help is the system's Help menu. Windows, Linux and the web keep the
in-window menu bar unchanged; --in-window-menus or VECTORCRAFT_IN_WINDOW_MENUS keeps it on macOS
too, and so does a menu bar AppKit refuses to build.

One menu model: the in-window menus and the native bar draw the same rows (menus::entry), and the
platform-free native_menu module lays them out, decides when to update (a cheap state hash; labels,
enabled and checked in place, a rebuild only when the structure changes) and hands key equivalents
back to egui as the key presses they were, so shortcuts, user overrides and focused text fields
behave as in the window and nothing fires twice. The muda backend (pinned =0.21.1, macOS only, no
unsafe) is apps/vectorcraft/src/mac_menu.rs, mirroring PhotoCraft's. ui.inspect reports
nativeMenuBar. Translations for the new labels in ja, es, zh-hans, zh-hant, cs and pt-br.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:45:31 +07:00
BFlat 8c4c665ee2
Merge pull request #540 from storytold/fix/eps-sources-restore
Fix #498, part of #505: EPS image sources read in turn, restore undoes dictionary changes (PLRM)
2026-10-08 23:44:50 +07:00
BFlat 4c2c606e25
Merge pull request #535 from storytold/pr/eps-spec-only-tests
EPS tests: interpreter programs written from the PostScript Language Reference
2026-10-08 23:44:33 +07:00
bflatastic b43b15a6e8 Part of #505: restore puts dictionaries back as they were at the save
The PostScript Language Reference (3rd ed., §3.7.3 "Save and Restore")
has `restore` reset composite objects in local VM to their values at the
`save`. The reader only restored the graphics state, so dictionary
entries changed between `save` and `restore` stayed changed: a program
that counts its open saves in a dictionary and refuses to go past a depth
stopped after that many saves in sequence, and the file fell back to its
preview. EPS files with many images, each drawn between `save` and
`restore`, are a likely case of #505; its reporter hasn't sent a file, so
this is part of it.

- While a `save` is open, `def`, `store`, `put`, `undef` and dictionary
  `copy` keep each entry's old value in a journal (counted against the
  memory budget); `restore` undoes it, newest change first, down to its
  save. A save restored already, itself or through an outer one, is no
  longer valid (`invalidrestore`, §3.7.3).
- `cachestatus` reports a device's cache sizes (chapter 8) instead of
  zeros: its last value, the most bytes one cached glyph may take, is what
  programs divide by.
- Tests (programs written from the reference): 100 saves counted in a
  dictionary under a depth limit, each dictionary change undone, saves
  restored twice, `cachestatus`'s glyph limit. Mutation-checked: without
  the journal or with a zero `cachestatus` the test fails. The import fuzz
  vocabulary has saves and restores around dictionary changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:43:51 +07:00
bflatastic 1d265951df Fix #498: EPS images with several data sources read them in turn
An image can take one data source per colour component
(MultipleDataSources, or `colorimage` with multi true). The PostScript
Language Reference (3rd ed., §4.10 "Images" and `image`/`colorimage` in
chapter 8) has the operator read the sources in turn, the same amount
from each. The reader drained each source on its own instead: when the
sources are procedures reading one file a row at a time, the first plane
took the rows of every component and the image came out in sheared
horizontal bands, as in #498.

- Data sources are read in turn by one reader, `read_sources`: a procedure
  once a round, a file or string a row a round, until each plane is full or
  its source ends. Single sources, procedure filters and masked images use
  it too; a string source resumes where it left off.
- Tests (`tests_images.rs`, programs written from the reference):
  procedures reading one file in the dictionary and `colorimage` operand
  forms (fails without the fix), separate string sources, rows padded to a
  byte at 1, 2, 4, 12 and 16 bits with an odd width (one and several
  sources), Flate PNG predictors with every row filter at an odd width.
  The import fuzz vocabulary has several sources reading one file and
  sources of uneven lengths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:43:49 +07:00
bflatastic eb255ef379 EPS tests: interpreter programs written from the PostScript Language Reference
Two EPS import tests become programs written from the PostScript Language
Reference (3rd ed.), with their own names and structure, covering the
interpreter features the importer relies on:
- `level_2_and_3_probes_read_as_vectors`: a resource category made from
  Generic, resources defined and found in it (§3.9), local and global VM
  (`currentglobal`, `setglobal`, `gcheck`, §3.7.2), `internaldict` probed
  through `stopped`, a halftone dictionary set and restored, `cachestatus`,
  `rootfont` and `currentcolorrendering`, drawing with its own procedures.
- `executable_strings_and_integer_keys`: shading dictionaries closed by an
  executable string (`(>>) cvx`, or a Level 1 builder with `counttomark`),
  procedures kept under integer keys run with `load` through `stopped`,
  `cvx`/`cvlit`/`xcheck` on strings.
Each was mutation-checked: making any of findresource, defineresource,
currentglobal, setglobal, gcheck, internaldict, sethalftone,
currenthalftone, currentcolorrendering, cachestatus, rootfont, stopped,
cvx, load, counttomark, cvlit or xcheck unknown fails a test, and so do
strings that `cvx` leaves literal, `load` refusing integer keys and
`gcheck` answering true.

The ROADMAP's EPS paragraph, file-formats row and last-updated line state
the PostScript features the reader supports; the legacy `.ai` comments in
the import module and the interpreter cite that format's published
specification (PRONOM fmt/423) for the `%AI` header comments and `u`/`U`
group operators the reader keys on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:43:48 +07:00
bflatastic 4eac7b505f Fix #506: drawing tools snap to Smart Guides as the Selection tool does
Every drawing tool now asks one snapper (guides::DrawSnap) for the points it
places: the Pen's and Curvature tool's anchors, the Pencil's ends, the shape
tools' start and dragged corner or radius (Rectangle, Rounded Rectangle,
Ellipse, Polygon, Star, Line Segment, Arc, Spiral, the grids), the Type tool's
click and frame and a new artboard's corners. Points land on other objects'
anchors, centres and paths ("anchor", "center", "path") or line up with their
anchors, edges and centres ("align"); hovering shows it before the press, the
Pen's guides end its rubber band, and the Pen lands on the path being drawn
too. Shift keeps a point to its 45-degree step (from Constrain Angle) or a
box's diagonal and slides it along that way into line with a target.
Preferences > Smart Guides > Construction Guides and Angles now act: a drawn
point near a guide through the point it leaves from lands on it.

Before, the Pen snapped only its press and showed nothing, and the shape tools
re-gathered targets on every drag step from the document showing their own
preview, so the dragged corner stuck to where the last step left it.

Performance: targets are gathered once per document state (keyed on the
document's uid and revision, now in ToolContext), from the art in the window,
and sorted, so the anchors, centres and lines near the pointer are found by
bisection. Leaving objects out of the targets no longer looks up each node's
ancestry (quadratic in the document's size): one pruned walk does it, which
also speeds up the Selection tool's moves and resizes.

The direction handles' HandleSnap (#494) is now a DrawSnap holding its own
targets (Targets::for_handle) for the drag: one cache, one lookup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:20:27 +07:00
BFlat 8b036df705
Merge pull request #515 from callmeBalloch/i18n-italian
Fix #514: Italian interface (it)
2026-10-08 23:14:48 +07:00
bflatastic 1d14f337db Fix #511: Live Corners on any path's corners (stars, polygons, pen paths)
Corner widgets only ever showed on live rectangles: CornerWidgets::of bailed
out unless the selection's live shape was LiveShape::Rectangle, and
object.setLiveShape only edited rectangle radii. A star is a plain path, so it
had no widgets with either selection tool.

- geom::corners: the corners of any path (anchors without handles between two
  straight sides) and the path with them cut round, inverted round or
  chamfered, each corner a circle tangent to both sides, its radius no larger
  than takes the cut halfway along its shorter side. Rectangles now cut their
  corners with it (bit-identical anchors and layout).
- doc::corners::LiveCorners/set_corners: one model for a live rectangle's,
  a live polygon's (new radii/kinds) and any other path's corners (new
  LiveShape::Path keeping the uncut outline, plain again once nothing is cut);
  radii scale with transforms (Scale Corners) and stay circular.
- object.setLiveShape takes anchor indices for `corners` on any path; polygons
  keep a shared radius as their sides change.
- Widgets: Direct Selection on any path, Selection on live rectangles and
  polygons; placed on each corner's bisector, the drag follows it, the red
  limit outline marks corners at their own limit; the angle preference and
  View > Hide Corner Widget apply. Corners dialog and the Properties and
  Transform panels' Corner Radius (now on polygons too) work on them.
- Tests for the star, the polygon and a pen path in geom, doc, tools, engine
  and ui-egui; docs and ROADMAP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:05:41 +07:00
bflatastic 7c5799aec6 i18n: Italian rows for strings added since the PR's base, consistency and fit fixes (review of #515)
- Italian rows for the strings main gained after the PR's base: the
  floating panels of #513 (Float Panel, Dock Panel, the drag hints, two
  window.float messages) and the GPU fallback status message of #519, so
  the completeness tests pass on current main.
- File > Document Setup... reads "Imposta documento..." like the dialog
  title and the Properties button, instead of "Impostazione documento...".
- The Properties panel's quick action "Arrange: Bring to Front" reads
  "Porta in primo piano": "Disponi: Porta in primo piano" was clipped at
  both ends of its fixed-width button.
- OpenType figure style "Proportional Oldstyle" reads "Proporzionali stile
  antico", matching "Tabulari stile antico".
- Blank line between the Italian test and the next item; ROADMAP's
  "Last updated" lists the Italian interface (#514).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:04:36 +07:00
callmeBalloch 4ba8a02107 Contributors: add callmeBalloch (Riccardo Balloch)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011iayep93edeimiAE8oSfaT
2026-10-08 23:04:33 +07:00
callmeBalloch 7c7ae55625 i18n: Italian interface (it)
Adds an Italian catalog (crates/ui-egui/src/i18n/it.tsv, 3,549 rows in
es.tsv's order) covering every menu string, every tl! literal, the
plurals and every status/error message, at the same scope as Spanish.
Standard Italian in sentence case, written clean-room from the meaning
of the English labels; the product, workspace, perspective preset and
language names stay in English as in es and ja.

Registered as "Italiano" with the one/other plural rule and
complete_menus; every it-* locale resolves to it. Tests: it joins
KEEPS_MENU_NAMES and COMPLETE_MESSAGES, italian_reads_as_italian checks
vocabulary and plurals, tags_map_to_languages the locale tags, and the
bundled-font glyph test covers Italian accents and guillemets. README,
ROADMAP and docs/development.md list the language.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011iayep93edeimiAE8oSfaT
2026-10-08 23:04:31 +07:00
BFlat 89ea46c805
Merge pull request #531 from storytold/fix/issue-508
Fix #508: PDF/.ai import keeps type strokes, wrapped lines and layer order
2026-10-08 22:54:27 +07:00
BFlat ffd31fd9cf
Merge pull request #534 from storytold/pr/linux-clipboard-probe
Linux: check the system clipboard for Paste off the UI thread (#510)
2026-10-08 22:52:37 +07:00
David Panusch b5759662c1 Control bar: Transform link opens the Transform panel; reference point locator redrawn
The Control bar's underlined Transform link opens the Transform panel as a
popover under it (reference point, X/Y/W/H, Rotate and Shear with their icons
and angle presets, flips, shape properties, Scale Corners, Scale Strokes &
Effects), as the Stroke link does the Stroke panel. X/Y/W/H stay inline while
the bar has room.

The reference point locator is now nine squares with the outer eight joined
around the box; the old outline was inset off the squares' centres.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 17:38:18 +02:00
bflatastic e63606826a Fix #508: PDF/.ai import keeps type strokes, wrapped lines and layer order
- Type left unfinished when a layer's marked content ends, and a clip that closes in a later layer,
  stay in their own layer (no stray "Page N" layer, no art moved to the next layer).
- Top-level layers stack as the pages mark them, so a layer whose art starts on a later page keeps its
  place; layers marked with no art come in empty.
- A stroke written as each glyph's outline stroked, right after (or before) the type, becomes the type
  object's stroke above (or below) its characters: the type stays one editable object.
- Spaces read from gaps wider than a space get their own tracking where even tracking would put the
  glyphs after them more than a tenth of an em off (barcode digit groups); lines are measured to their
  last visible glyph, so a wrapped line's trailing space no longer spreads into the tracking.
- Lines wrapped in a frame (each wrapped line ending in a space, one left edge, font, size and leading,
  with an optional paragraph spacing) come back as one area type object, left aligned or justified,
  only where laying it out breaks the lines exactly where the file does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:37:37 +07:00
bflatastic 71371b9d58 Linux clipboard probe: look only while Paste depends on it, stop at once (review of #510)
- The worker reads the clipboard only while nothing is copied in the app
  and a document is open (as the in-line check did before), and idles on
  a channel otherwise; it sends a verdict and wakes the UI only when the
  answer changes.
- The in-line check (Windows, macOS, web) keeps its short-circuit: it
  doesn't open the system clipboard after an in-app copy or without a
  document, as before the PR.
- A dead worker hands the check back to the UI thread instead of
  freezing the last verdict.
- Dropping the app wakes the worker and waits (250 ms at most) until it
  has let go of its clipboard handle: on X11 the last arboard handle
  alive hands what the app copied to the clipboard manager, and a
  detached worker holding it would lose that handover at exit.
- The factory stays in `Services` until the first frame takes it (no
  extra app fields); main.rs installs it with `cfg!(target_os = "linux")`.
- Tests trimmed from five to three that share tests_sysclip's helpers:
  the frame never waits on a slow clipboard and only the probe thread
  reads it (nothing read without a document), the probe rests after an
  in-app copy and lets go of its handle when the app drops, and a dead
  probe falls back to the in-line check. The in-line case is already
  covered by tests_clipboard.
- ROADMAP (Last updated, Platforms, Shipped so far) and
  docs/development.md (Linux: clipboard owners that never answer).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:36:44 +07:00
Oscar Sebastián Mellado Bustos 5db200d392 Linux: check the system clipboard for Paste off the UI thread
`has()` on an X11 clipboard owner that never answers can block for
seconds; the app called it every 0.25 s on the UI thread to decide
whether Paste is enabled, so a stuck owner froze the frame loop (the
window stopped drawing and could not be closed).

`clipboard_probe` owns a second clipboard handle on a worker thread,
publishes its verdict over a channel and wakes the UI only when it
changes; the frame reads the latest verdict without ever blocking.
Without a factory the check stays in line, throttled, exactly as before
(the web shows SVG text only; hosts that don't install one keep the old
path).

The factory is installed on Linux only for now (the environment the bug
reproduces in); other platforms keep the in-line check, so this cannot
change their behaviour.

Tests: a fake clipboard whose `has()` blocks on a gate, a probe factory
sharing a recorder, and a headless frame whose elapsed time is measured.
They assert the frame does not wait on the clipboard and that the check
runs on the probe thread, that the probe's verdict reaches `system_paste`
and the Paste menu, that dropping the app stops the probe, and that the
in-line check (no factory: the web, older hosts) still works.
2026-10-08 22:34:29 +07:00
BFlat c0396c0761
Merge pull request #524 from storytold/fix/issue-504
Fix #504: Convert corner/smooth for a path selected as a whole with the anchor tools
2026-10-08 22:32:32 +07:00
BFlat c7f1e00955
Merge pull request #521 from storytold/fix/issue-501
Fix #501: a Pen drag out of the first anchor always closes the path
2026-10-08 22:31:56 +07:00
BFlat 3c91ca8a1d
Merge pull request #517 from storytold/fix/issue-494
Fix #494: Pen + Cmd edits the path being drawn; Pen + Alt reshapes segments; handle drags fixed and fast
2026-10-08 22:31:38 +07:00
BFlat 7e3bcc48fe
Merge pull request #519 from storytold/fix/issue-502
Fix #502: no startup crash on dual-GPU Linux desktops under Wayland
2026-10-08 22:31:07 +07:00