Commit Graph
379 Commits
Author SHA1 Message Date
dotCooCoo 7da7c2c456 Merge main into fix/artboard-files-ask-before-replacing 2026-11-11 23:51:03 -08:00
dotCooCoo b262d10e89 Save and Export: files written beside the picked one ask before replacing a file there
A save or export that writes a file per artboard, linked images or image
maps names them after the file picked in the save panel, which asked only
about that name. A file already there under one of the other names was
replaced without a question.

Save As, Save a Copy, Save as Template, Save and Export now check those
files before writing anything. When any is there, nothing is written and
a replaceFiles question names it (and lists all of them when there are
several). OK runs the save or export again on the document that asked and
replaces the named files; a file it would now write that the question did
not name is asked about again. Cancel writes nothing. A background save
or export checks from its worker and asks once it ends, after a dialog
open then. Files the document's last Save or Save As wrote are replaced
without asking.

Services::exists is now an Arc<dyn Fn(&str) -> bool + Send + Sync>.
2026-11-11 23:39:32 -08:00
BFlat 5e63104d88 Merge pull request #6800 from dotCooCoo/fix/plugin-automation-install-approval
Plug-ins: an install that automation asked for is not approved in its dialog
2026-11-12 14:16:59 +07:00
dotCooCoo ad05c3b99d Plug-ins: an install that automation asked for is not approved in its dialog
An approval question that a control request, MCP, injected input, or a
file dialog one of them opened leads to now keeps OK disabled and
refuses every confirm, a person's click included. The dialog says to
choose Object › Plug-ins › Install Plug-in…, and ui.installPlugin answers
approval: "personMustStartInstall". The person's own Install Plug-in…,
File › Open or drop inspects the module again and asks a new question
with its half-second delay.

The origin is fixed when the request is made and goes with a native
file dialog's deferred answer and the web picker's answers, which now
arrive apart from drops and from window.vectorcraft.openFile (always
automation). A question about taking another module's place now opens
in the approval dialog, and automation's replace: true no longer skips
it. A module that needs no approval still installs at once.
2026-11-11 21:56:58 -08:00
dotCooCoo 832fad16e0 Merge main into feat/hang-report 2026-11-11 21:17:30 -08:00
Dylan M. Taylor a971a14898 Fix Flatpak updates and bump to 0.24.1 (#6649)
* fix(flatpak): allow release checks and self-update helpers

* test: keep Flatpak permission parsing within strict Clippy rules

* chore: bump version to 0.24.1 for the Flatpak update fix

* test: locate CLI binaries after Nextest archive relocation

* docs: explain the Flatpak update permission bootstrap
2026-11-11 21:30:40 -05:00
dotCooCoo d7a32d09ec Merge main into feat/hang-report 2026-11-11 18:28:39 -08:00
BFlat ed412fb73b Merge pull request #6661 from dotCooCoo/fix/clipboard-read-time-limit
Clipboard: Linux and BSD reads wait 2 s at most for the app that copied
2026-11-12 09:22:11 +07:00
dotCooCoo e9942b69d2 Help: a frame run while a file dialog waits is timed for the hang report
The input hook, the logic and the interface of a frame now mark their
time as timed whatever the activity around them, so a frame the system
runs while an in-line file dialog waits for the user is timed too, and
the dialog's wait is not timed again once the frame ends.
2026-11-11 17:36:11 -08:00
dotCooCoo 7f5e4519a5 Help: input in a focused floating window is timed for the hang report
The end of a frame counted the renderer as busy only when the main
window had the focus, so a stall drawing input in a focused floating
panel or document window wrote no hang report. A floating window that
has the focus and is not minimized now counts too. A frame that sends
that window commands to minimize or hide it, or to move or resize it,
ends idle, including commands its own pass sent, which are noted
before egui passes them on.
2026-11-11 17:26:09 -08:00
dotCooCoo ab91a4a705 Clipboard: a paste after a late answer reads the clipboard again
The app that answers a late read may have lost the clipboard while the
paste waited. Once the answer comes, the paste makes the same read again
and uses the new answer, for arboard's reads and the core protocol's
text read alike.
2026-11-11 17:23:43 -08:00
dotCooCoo 892d87ce55 Clipboard: a paste's reads after a late answer wait as long as the paste
The text and file-list reads that follow a late answer now wait until
10 s after the unanswered read was sent, not 2 s from when they start,
so a slow text answer is still pasted. Text that is blank or names a
picture is replaced by the bitmap only when the paste asks for one.
2026-11-11 17:16:05 -08:00
dotCooCoo d8be61ddb1 Help: making a save dialog's folder is timed for the hang report
An in-line save dialog that first makes its folder marked the folder
work as the dialog too, so a stall in making the folder wrote no hang
report. The folder is now made before the dialog is marked, on the
background dialog thread as well, and a test checks the order.
2026-11-11 16:27:24 -08:00
dotCooCoo 2ce702eda0 Clipboard: a paste after an unanswered Wayland text read waits for its answer
The core-protocol text clipboard (used where the compositor has no
data-control protocol and there is no X11) failed a paste at once after
its 2 s read timeout, so the paste took the internal clipboard even when
the other app's text came within the paste's 10 s limit. It now keeps a
text read that got no answer in its wait, as the arboard path does, and
the paste waits for that answer on its background thread until 10 s
after the read was sent. The answer is pasted unless it is empty or the
text copied here.
2026-11-11 16:20:52 -08:00
dotCooCoo 14c8385df3 Clipboard: a paste after an unanswered read waits for its answer
When the check whether the clipboard still holds what VectorCraft copied,
or one of a paste's own reads, gets no answer within its 2 s, the read is
kept. The paste then waits for that answer on its background thread, up
to 10 s after the read was sent, instead of failing its other reads at
once and pasting the internal clipboard. When the answer is what
VectorCraft copied, or none comes, the paste takes the internal
clipboard; otherwise the clipboard is read as a paste reads it, with that
answer standing in for its read. An answer that came before the paste is
dropped and the clipboard is read again.
2026-11-11 15:49:27 -08:00
dotCooCoo 7f641b9c10 Help: a stalled interface writes a hang report, and Copy Troubleshooting Info copies it
When the interface thread stays in one part of a frame for 3 s, a
watching thread writes a hang report to the log and to
logs/hang-report-<process id>.txt. The report gives the part of the
frame (input hook, logic, interface, or the renderer after a frame in
which any window had input), a system clipboard call in progress, the
last 8 different command ids, the last 16 frame times, the platform,
window system, desktop and session type, Flatpak, graphics adapter, the
present mode and frame latency the app asks for, the running time and
the number of open documents. It holds no document contents, file paths
or command parameters. The interface thread marks its stages with a few
atomic stores a frame, and the watching thread reads those marks without
waiting on it.

The process keeps the report file locked until the interface answers
again, then removes it. A file nobody holds at a later launch was left
by a session that was closed while it did not answer: the launch writes
the report to the log, moves the file to logs/hang-report.1.txt and,
unless another start-up message is showing, says so in the status bar.
Help › Copy Troubleshooting Info puts the platform facts, the recent
commands and frame times and both sessions' reports on the clipboard for
a bug report. An in-line file dialog, an open menu of the macOS menu bar,
and the time after a frame that minimizes or hides the window or starts
moving or resizing it are not timed.

The menu label and the two status messages have rows in every catalog.
2026-11-11 15:19:35 -08:00
dotCooCoo 78f412f0a3 Clipboard: a paste's bitmap read waits for the owner off the UI thread
A paste on Linux and the BSDs read the bitmap on the clipboard worker but
waited up to 10 s for it on the UI thread, so a bitmap from an app that
never sent its data froze the window long enough for the compositor to
offer to close it.

The paste now sends the bitmap read to the worker and returns at once;
its background thread waits up to 10 s for the answer and converts it to
PNG. While that read is open, other reads fail at once instead of
queuing behind it. Each read gets its own answer channel, so a late
answer is dropped. The check of whether the clipboard still holds the
app's own bitmap waits 2 s at most, as text does.
2026-11-11 14:57:01 -08:00
dotCooCoo e3093034ea Scripts: opening a macOS menu reads the Scripts folder again
With the macOS menu bar, File › Scripts was read only at startup and
when the window became active, so a script added while the window
stayed active did not appear. The native menu now reports a menu
opening (Event::Opened, when AppKit begins tracking), and
native_menu::run reads the folder again, as opening the in-window File
menu does. Menu updates wait until tracking ends, so the new listing
shows the next time the menu opens.

Docs: docs/mcp.md (File › Scripts), docs/target-app-parity.md.
2026-11-11 13:47:41 -08:00
dotCooCoo 825620eb6c Clipboard: Linux and BSD reads wait 2 s at most for the app that copied
arboard's Wayland data-control read waits for the app that owns the
clipboard to send its data with no time limit, and its X11 read waits up
to 4 s for each format it tries. These reads ran on the UI thread: a
Copy or Cut checking what the clipboard held, a paste, and the paste
check once its background thread is gone. A clipboard owner that never
sent its data froze the window.

On Linux and the BSDs, arboard's reads now run on a worker thread with a
clipboard handle of its own. Text and file lists wait 2 s at most and a
bitmap 10 s; the core-protocol fallback's text reads already wait 2 s.
While a read is unanswered, later reads fail at once. Writes stay on the
UI thread's handle.

The core-protocol fallback's worker is now generic and built on every
platform. On X11, closing the clipboard within 25 s of a read that got
no answer waits for that read to end, so the app's own handle is the
last one and hands the copy to the clipboard manager. On data-control
and the core protocol, closing does not wait for an unanswered read.
2026-11-11 12:06:33 -08:00
dotCooCoo 5ac7d97d85 Guides: ruler guides are document objects on their layers
Ruler guides were a list kept beside the layers. Each guide is now an
object of its layer or sublayer, always directly in it and above the
layer's art. These behave as on main:

- Guides draw on screen only. Exports (SVG, PDF, PNG, PSD), Fit All,
  Select All, the art bounds, clicks and marquees, and a layer's
  Pathfinder and Transform effects leave them out. The Layers panel
  lists them as guide rows of their layer, the highest guide.list
  index first.
- Deleting a layer deletes its guides, and merging layers keeps their
  guides in the merged layer.
- The guide commands number guides as guide.list does, in the order
  they were made.

New: each guide takes an id from the document's object ids. An object
command given a guide's id fails with an error, and node.move cannot
put a guide into a group or out of its layers. A guide made while an
opacity mask, a symbol or a pattern is edited moves to the top
visible, unlocked layer when editing ends.

File format: native files still save the guides in the document's
guides list, in every file version, so older builds read them. Each
entry may now also carry the guide's id, name, locked and hidden
flags; older builds ignore those fields. Opening a file puts each
saved guide on its layer (on the top visible, unlocked layer when the
file names none or a layer it does not have), and each saved guide
counts against the object limit for opening a file. A ruler guide node
that a file holds below a layer's art moves up to the layer's guides,
and one anywhere else (in a group or another object, beside the
layers, or in a symbol) is removed. Ruler guides read from an .ai file
become guide objects on the layer they were on, numbered in the order
the file lists them.
2026-11-11 09:52:28 -08:00
dotCooCoo 52efba54aa Scripts: File › Scripts lists the Scripts folder, subfolders as submenus
File › Scripts now lists the .js and .jsx files of the Scripts folder next
to the preferences, each named after its file without the extension, with
each subfolder as a submenu, above Check Script… and Other Script…. The
help page describes this listing:
https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/install-and-run-scripts.html

Choosing a listed script runs it through script.run without the warning
Other Script… shows. script.listInstalled returns the same listing, and
ui.runInstalledScript {path} runs one entry.

VectorCraft's own rules: the folder is read off the UI thread when the
app starts, when its window becomes active and when the File menu of the
window's menu bar opens; only names are read; links, junctions, hidden
and system entries are left out and checked again before a run; one read
stops at 2,048 entries, 512 scripts, 128 subfolders, 4 levels or 250 ms
and the menu then notes that some scripts were not listed. Under an
automation read root, script.listInstalled and ui.menu.list leave out a
folder outside the root.

#1183 (LloydNicholson) also proposed a Scripts menu listing a folder.
2026-11-10 17:46:36 -08:00
Sven Lafebre eadf64fbab Fix #6335: Color Settings are remembered across restarts
edit.colorSettings set only the process-wide colour settings, so the RGB and
CMYK working spaces, intent and black point compensation went back to the
defaults at every start, although the profiles color.loadProfile loads are
kept (#2168, #2174). The engine now writes them to a settings file when they
change (Session::attach_color_settings), and the desktop app and
vectorcraft-cli keep that file as `Color Settings.json` next to the
preferences, attached right after the profile store so a saved working space
may be a loaded profile. Saved settings that can't be used (a profile that is
gone, a damaged or oversized file) leave the defaults with a log record, and
the next change writes over them. Nothing is read or written with
VECTORCRAFT_NO_PREFS.
2026-11-10 21:28:07 +01:00
dotCooCoo 7b44ef5737 Merge main into feat/script-run 2026-11-09 23:43:37 -08:00
dotCooCoo cc03fade6e Scripts: the growth budget counts every art store, with CLI and source fuzz tests
A document a script opens now counts the art in its graph designs and in
the original of the pattern being edited toward the growth allowance.
`Document::art_roots` and `art_roots_mut` list every tree of a document's
art; `any_node`, `edit_nodes_where` and the script's object count use them.

`script.run` checks the depth of `args` without recursion before it copies
or writes them out, so `args` nested 10,000 levels deep is refused with the
place it went past 64 levels instead of overflowing the stack.

New tests: graph-design art and the growth allowance, `args` nested 10,000
levels deep from a script (a RangeError) and from a caller, `run --cmd
script.run` on the command line with a report and with a thrown error, and
a property test that sends arbitrary source through `script.run`.
2026-11-09 22:00:04 -08:00
dotCooCoo 9ccea9cfcb Commands: engine.apiReference returns the command API reference in Markdown
engine.apiReference {} -> {markdown} writes a reference from the built-in
commands' parameter schemas each time it runs: a section per command that
has a schema, in registry order, with its label, menu path, API levels,
what it writes, cost, summary and return, and a table of its parameters
(type, range with included or excluded ends, unit, JSON or worked-out
default, required, levels and description; object members as dotted
rows). Commands without a schema, plug-in commands included, are left
out. Schema text is escaped so it stays plain text in its cell, control
characters become spaces, and a reference past 1 MiB is an error rather
than a cut-short text. The command needs no document.

MCP serves the same text as the fixed resource
vectorcraft://commands/reference (text/markdown; charset=utf-8); the
other resources still read as JSON.

The command's own schema raises the schema API level to 2. Its label and
its size error have rows in every catalog that needs them.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-09 21:24:13 -08:00
dotCooCoo 2c0d09e079 Scripts: File › Scripts › Other Script… runs JavaScript files
File › Scripts › Other Script… picks a .js or .jsx file, shows a warning
that can be turned off in Preferences › General, and runs the script
against the open documents through the `vc` object. The new
`script.run` and `script.stop` commands run and stop a script over MCP.

- A run is one transaction. Each document it changed gets one undo step
  named Run Script. An uncaught error, a limit or a stop puts every
  document, the paint, the clipboard, menu state and preferences back.
- A command that fails inside a run, or whose result is too large to
  reach the script, is undone and throws an error the script can catch.
- Files a command wrote stay on disk and the report names them, also
  when the run is stopped from the quit question.
- While a script runs, other commands that change anything fail with a
  busy error; MCP reports it as JSON-RPC error -32003.
- In the app the run advances one slice per frame with a Stop button in
  the status bar. A run that adds a great many objects asks whether to
  continue; Stop and Escape end it.
- Commands that change state outside the documents, such as prefs.*,
  plugin.* and file.place.queue, are refused to scripts.

Docs: docs/mcp.md, docs/gaps.md, docs/roadmap.md,
docs/target-app-parity.md.
2026-11-09 18:35:41 -08:00
Ahmed Gomaa 7fa506c3f8 Merge remote-tracking branch 'upstream/main' into fix/macos-native-cursor-delivery 2026-11-09 14:13:27 +02:00
Ahmed Gomaa aec326b6c6 macOS: deliver canvas cursors through AppKit pending a winit fix
On macOS the canvas paints tool cursor glyphs into the frame, so they
trail the pointer by a frame or more (#2292). This interim adapter
delivers the same glyphs as native NSCursors, which AppKit moves
independently of canvas redraws.

ui-egui prepares cached 1x/2x RGBA requests from the existing cursor
rasterizer and hotspots (transparent padding only) and keeps returning
a visible system fallback icon. The desktop host builds NSImage/NSCursor
objects with point-sized images and hotspots, owns cursor-rectangle
suspension and restoration, and hands the cursor back on menu tracking,
focus loss, empty passes, cursor overrides and shutdown.

Windows/X11, Wayland and web delivery are unchanged. No artwork, no
production unsafe, no new dependency package: only four AppKit features
are enabled on the already-shipped objc2-app-kit. Remove once the pinned
winit sizes macOS cursor images and hotspots in points.

Addresses #2292.
2026-11-09 13:44:32 +02:00
HassanKhan 11779d6d46 Merge remote-tracking branch 'upstream/main' into feat-4936-custom-dictionary
# Conflicts:
#	docs/gaps.md
#	docs/roadmap.md
#	docs/target-app-parity.md
2026-11-09 15:04:56 +05:00
HassanKhan 5bef0ed79a Part of #4936: custom dictionary and Ignore All commands
text.spelling.addWord, removeWord and changeWord are Check Spelling's Add
and Edit Custom Dictionary's Add, Delete and Change; text.spelling.dictionary
lists the words. They live in craft-proof, which every language's check
reads. The desktop app and vectorcraft-cli keep them in
`Custom Dictionary.txt` next to the preferences (none without preferences);
elsewhere they last until the app closes.

text.spelling.ignoreAll is Ignore All: the active document's checks skip the
word while it is open; not saved, not undoable, and not a change to the
document's revision.

Behaviour: https://helpx.adobe.com/illustrator/desktop/design-with-text/edit-format-text/check-and-correct-spelling.html
2026-11-09 13:54:08 +05:00
dotCooCoo 950d149e45 Plug-ins: test that run and mcp need the start-up flag for allowHeavy 2026-11-08 22:16:35 -08:00
dotCooCoo 7431486afa Plug-ins: mcp refuses --allow-plugin-grants with automation roots
A server confined with --automation-read-root or
--automation-write-root has no plug-in store, so a grant accepted under
the flag could not be written to grants.json and recorded grants were
not read. mcp now refuses the combination at start-up.

The help text, docs/plugins.md and docs/mcp.md state that a confined
server does not install a module that lists permissions or asks for a
heavy budget, and that with VECTORCRAFT_NO_PREFS set a grant accepted
under the flag lasts for that session only.
2026-11-08 21:54:46 -08:00
dotCooCoo ae52c802e4 Plug-ins: test that mcp --headless needs the start-up flag for grants
plugin_grants_need_the_start_up_flag now drives `vectorcraft-cli mcp
--headless` over stdio. plugin.install with grant is refused without
--allow-plugin-grants and accepted with it.
2026-11-08 21:47:33 -08:00
dotCooCoo 391705af50 Merge main into fix/plugin-grant-app-approval 2026-11-08 21:10:29 -08:00
dotCooCoo 9ae57b03c0 Plug-ins: the texts say a grant accepted under the flag stays recorded
A grant accepted under --allow-plugin-grants is written to grants.json like a
person's approval and counts as approved in later sessions and in the desktop
app. The CLI usage text, the plugin.install params text and docs/plugins.md and
docs/mcp.md said only a person's approval in the desktop app records one.
2026-11-08 21:10:26 -08:00
BFlat 1b8f273255 Merge pull request #6277 from dotCooCoo/fix/titlebar-variable-doc
Linux: docs say which VECTORCRAFT_TITLEBAR values take precedence
2026-11-09 13:06:49 +08:00
dotCooCoo e7c3307f07 Merge main into fix/plugin-grant-app-approval 2026-11-08 20:58:47 -08:00
BFlat baa7248e76 Merge pull request #5158 from dotCooCoo/fix/ai-os23-2831
.ai import: names that aren't UTF-8 can be read in a legacy code page
2026-11-09 12:46:30 +08:00
dotCooCoo 05e3b99bf7 Linux: comments say which VECTORCRAFT_TITLEBAR values take precedence 2026-11-08 20:24:12 -08:00
dotCooCoo 3258785476 Merge main into fix/ai-os23-2831 2026-11-08 19:44:24 -08:00
dotCooCoo 36755be821 Merge main into fix/plugin-grant-app-approval 2026-11-08 19:30:19 -08:00
Dylan M. Taylor 9879909976 Merge pull request #6271 from dotCooCoo/fix/updates-install-at-exit
Updates: the updater reports installing, ready, installed and failed, and installs at exit
2026-11-08 22:09:52 -05:00
dotCooCoo d3a323284c Merge main into fix/ai-os23-2831 2026-11-08 18:52:59 -08:00
dotCooCoo 81149bb945 Linux: VECTORCRAFT_TITLEBAR takes precedence over System Title Bar for one run
On Linux and the BSDs, VECTORCRAFT_TITLEBAR=app now uses the app bar as the title bar with System Title Bar on. Before, System Title Bar kept the desktop's frame while the Preferences note said the variable chooses the title bar.

While the variable is set, Preferences dims System Title Bar, and the note that System Title Bar takes precedence over VectorCraft Title Bar on Every Desktop does not show. macOS and Windows do not read the variable.
2026-11-08 18:31:31 -08:00
dotCooCoo ac076655db Updates: the updater reports installing, ready, installed and failed, and installs at exit
craft-update moves from c5a1cbfb to the head of storytold/craft-libs#696.
The check result window now shows for every status but idle, so the first
start after an update reports that it installed or why it failed. Restart
to Update on a ready update asks the app to close.

The install helper now starts when the app exits. on_exit calls
Updater::start_pending_update through VectorcraftApp, because the macOS
exit in end_before_teardown ends the process without dropping the app.
2026-11-08 18:12:22 -08:00
dotCooCoo 727a611ef7 Merge fix/plugin-grant-module-hash into fix/plugin-grant-app-approval 2026-11-08 16:35:45 -08:00
dotCooCoo e2beb714b0 Merge main into feat/help-bar-visibility 2026-11-08 14:56:29 -08:00
dotCooCoo 33489f9c1a Merge main into fix/plugin-grant-app-approval 2026-11-08 11:28:38 -08:00
dotCooCoo 1b30f960e6 Merge main into fix/plugin-grant-app-approval 2026-11-08 11:27:11 -08:00
dotCooCoo a4a516e82f Plug-ins: only a person can approve a plug-in's permissions and heavy budget
`plugin.install` accepted `grant` and `allowHeavy` from any client, so
the program installing a plug-in could answer its own permission
prompt.

The desktop app now shows an approval dialog that names the module,
its hash and what it asks for. Confirming it gives the engine a
one-use approval tied to that module id, hash and permission list. A
control or MCP request and a frame of synthetic input cannot confirm
the dialog, and Enter does not confirm it.

Without such an approval, `grant` and `allowHeavy` are refused. The
new `--allow-plugin-grants` flag on `mcp` and `run` lets a person who
starts a headless session accept them from requests. The flag cannot
be combined with `--connect`. A module already approved in the desktop
app still installs through its stored grant.
2026-11-08 11:03:38 -08:00