Commit Graph
254 Commits
Author SHA1 Message Date
gianlucafiore a6307b3666 feat: add quick searchable layer command 2026-10-08 23:17:03 -03:00
gianlucafiore ec9f91ec75 fix test failed 2026-10-08 18:47:54 -03:00
gianlucafiore af3118b826 fix: preserve layout plot settings and CTB block colors 2026-10-08 18:29:14 -03:00
Hakan Seven 9519614e91 Merge pull request #1663 from ramox81/codex/sweep-surface-associativity
Associative swept surfaces in the drawing's network
2026-10-08 14:44:25 +03:00
Hakan SevenandClaude Opus 5.5 340104bf1b feat(options): interface scale for the whole window
On a non-Retina screen macOS draws the interface at 1x, which reads small
on a Full HD monitor, and there was no way to enlarge it. Options >
Display now offers an interface scale of 75–200 % in 25 % steps, applied
through the window's scale factor on top of the display's own and kept
with the user settings. It is a list rather than a slider because the
dialog rescales under the pointer as the value changes.

Fixes #1655

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 14:41:46 +03:00
ramox81andClaude Opus 5.5 48c3c433a5 feat(sweep): associative swept surfaces in the drawing's network
Swept surfaces made with SURFACEASSOCIATIVITY on keep their profile and
path and are written as a swept-surface action of the drawing's
associative network, reading the profile and path and their scale and
twist expressions. They follow edits of their sources.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 13:29:55 +03:00
Hakan SevenandClaude Opus 5.5 69057c55da feat(viewport): optional touchpad pan for wheel-scrolling touchpads
Outside macOS a touchpad's two-finger drag arrives as wheel scrolls that
nothing tells from a wheel. A new option (Options, off by default) makes
every scroll pan and Ctrl+scroll — what a pinch sends there — zoom.

Fixes #1560

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 11:07:37 +03:00
Hakan SevenandClaude Opus 5.5 9adb6f59c8 fix(copy): a copy reacts only to what was copied with it
COPY and PASTE kept the source's reactors on each copy, so a copied
dimension still pointed at the source's dimension association (and
boundary or group members at the source hatch or group). Another
application reports such a drawing as damaged and, after recovery,
moves the dimensions. A copy's reactors now follow only targets copied
with it; group copies give their members the new group's reactor; and a
drawing opened with such stray dimension reactors has them dropped.

Fixes #1645
Fixes #1649

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 08:34:49 +03:00
Hakan SevenandClaude Opus 5.5 7a8ec02003 feat(options): command line text colour and a fonts folder
Display gets a command line text colour (blank keeps the theme's); it
covers history, prompts and the input, while errors stay red. Files
lists the fonts folder that text resolution searches, so .shx files can
be added by hand; opening it creates it first.

Discussions #1493, #1372

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 08:50:12 +03:00
Karim Jerbi 7aafd9c710 refactor(selection): split 31-field SelectionState into five sub-structs
SelectionState now holds view, gesture, input, menu and orbit sub-structs; all 450 access sites updated mechanically with no behavior change. Deletes three write-only dead fields (box_last, box_last_crossing, poly_last_crossing). Hand-rolled clears in commands and dim_viewport route through the new clear methods; bench fixture updated. Full suite: 1976 passed / 0 failed / 25 ignored.
2026-10-06 20:22:04 +01:00
Karim Jerbi 8c2cfa2c8f fix(viewcube): cache UCS picker names behind an epoch
The two per-frame ViewCube blocks rebuilt the named-UCS name list (N String clones plus a Vec) every frame; now Scene::cached_ucs_names memoises it behind ucs_epoch and the picker takes the Arc, so frames cost a refcount bump. Bumped on UCS SAVE, UCS DELETE, RENAME UCS, record-API ucss patch, file-open, and undo Full-swap. Tests: cached_ucs_names_returns_same_arc_until_bump pins the hit path; cached_ucs_names_invalidated_by_bump pins rebuild with new content. Full suite: 1976 passed / 0 failed / 25 ignored.
2026-10-06 20:10:23 +01:00
Hakan SevenandClaude Opus 5.5 bd37a2f969 review(#1627): the snapshot-save preparation is native-only
It stamps sheet set data, which the web build does not have; the wasm
check failed once #1627 split it out of prepare_native_save.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 21:09:40 +03:00
Hakan Seven 711799371a Merge pull request #1627 from ramox81/codex/plotdate-refresh
Fields: evaluation events, UPDATEFIELD, FIELDEVAL, per-field shading and PlotDate redraw.

# Conflicts:
#	Cargo.lock
#	src/entities/field.rs
2026-10-06 20:42:01 +03:00
Hakan SevenandClaude Opus 5.5 1eae36e726 Cargo: codec 76d2a1c, kernel e652b4d, graph 0545fa9; text styles, templates, solid edges
- Text styles keep their TrueType typeface through save and reopen (codec
  reads and writes the STYLE record's ACAD extended data) (#1633)
- Unnamed shape-file entries no longer show in text style lists (#1634)
- Save As offers DWT 2018; NEW asks for the template to start from, while
  Ctrl+N and the quick-access New run QNEW with the default template (#1635)
- An edge next to an earlier fillet of the same radius rounds together with
  it (kernel); the solid stays drawn and pickable while edges are chosen
  (#1625, #1107)
- A full cache rebuild drops the B-rep cache too, so an undone fillet does
  not come back with the next edge operation (#1107)
- Selected solids in shaded styles highlight only their visible edges (#1031)
- VIEW ISO / SWISO / SEISO / NEISO / NWISO snap to the isometric corners

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 18:32:43 +03:00
Hakan SevenandClaude Opus 5.5 178c7dff41 fix: open-issue sweep — drawing, plot, snap, layout and UI fixes
Fixes:
- Font prompt no longer lists bundled ltypeshp/qcadshp shape files (#1626)
- Wide polylines step at a discontinuous segment width; PEDIT marks the
  current vertex; keyword steps refresh the command preview (#1628)
- Radius-0 fillet drops the zero-length segment it left, so the corner
  fillets again (#1422)
- FILLET Trim / No trim option (#1558)
- True-colour wires plot in their own colour; colour picker stores the
  value it shows (#1621)
- Model tab keeps its page setup; "Save changes to layout" in Model (#1620)
- QNEW default template in Options > Files; .dwt in the open dialog
  (#1134, #1113)
- GRIDUNIT / GRIDMODE / PERSPECTIVE variables (#1618, #1524)
- PTYPE (#1433)
- ZOOM nX / nXP (#1465)
- CHSPACE between model and paper space through a viewport (#1428)
- Moving a dimension keeps its automatic text placement
- Shell icon; "&&" button labels (#1554)
- LINETYPE Load from a .lin file (#1588)
- XLINE / RAY hide the crosshair arms (#1437)
- Dynamic-input boxes keep clear of the crosshair and each other (#1546)
- Snap marker colour setting, dark default on light canvases
  (#1497, #1229, #1128)
- Dimension style precision as a 0.00 pattern dropdown (#1426)
- Node graph nodes left of the origin no longer clip away (#1592)
- Collapse button in the command history header (#1094)
- Freeze-in-current-viewport toggle in the ribbon layer list (#1466)
- Geometric Center object snap for closed polylines (#1369)

New strings translated in all 21 locales.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 15:59:30 +03:00
ramox81andClaude Opus 5.5 1c242eb489 Fields: stored values on redraw, evaluation events, per-field shading
MTEXT draws its stored text instead of re-evaluating fields on every
redraw. Fields update on their evaluation events as the reference does:
open (1), save (2, not autosave), plot (4) and REGEN/REGENALL (16), each
masked with the drawing's FIELDEVAL (variable dictionary, 0-31, with the
reference's prompt and message), and the new UPDATEFIELD command
(selection, attributes of selected block references, "N field(s)
found." / "N field(s) updated."). A Date field (on demand only) keeps
its value until UPDATEFIELD. The FIELDDISPLAY gray box now covers each
field's own glyphs, one box per line it spans, instead of the whole
text. Codec moved to the update_fields / field_spans revision.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 11:38:01 +03:00
ramox81andClaude Opus 5.5 71cebbb3fe Plot: redraw PlotDate hosts inside blocks and attributes
A plot stamps PlotDate fields, but the redraw only dropped the host's
own tessellation: an attribute is drawn by its INSERT and a host inside
a block definition by every reference to the block, so both still
showed the old value on screen and in the plotted output. The changed
hosts now redraw through their INSERT / the block's references (block
cache refreshed), without re-tessellating anything else. The codec is
patched to the field format code fixes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 10:37:04 +03:00
Hakan Seven fbe55bab37 Merge pull request #1613 from ramox81/codex/sheet-set-manager
Sheet Set Manager, NEWSHEETSET / OPENSHEETSET and sheet set fields, with review fixes.

# Conflicts:
#	Cargo.lock
#	src/app/control/actions.rs
#	src/app/mod.rs
#	src/app/settings.rs
#	src/app/update/dialog.rs
#	src/app/update/file.rs
#	src/app/update/mod.rs
#	src/app/view/mod.rs
#	src/ui/dock.rs
#	src/ui/ribbon/mod.rs
#	src/ui/window/field_dialog.rs
#	src/ui/window/mod.rs
2026-10-06 09:49:38 +03:00
Hakan SevenandClaude Opus 5.5 3a5c1dbb7d fix(sheetset): read drawings off the UI thread
The wizard's folder scan, Import Layout as Sheet, the template layout
lists and the drawing cache behind Model Views, Place on Sheet, callout /
label blocks and block previews parsed whole DWGs on the UI thread. They
now go through the shared `background_task` worker: a cache miss reads the
drawing and handles the message that needed it again. Block previews lend
the cached drawing to the preview scene instead of cloning it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 09:33:04 +03:00
Hakan SevenandClaude Opus 5.5 8b9049c604 fix(view): keep named views of earlier versions at their place, in f64
A VIEW record's centre is an offset from its target in view coordinates.
Views saved by earlier versions stored the target itself as the centre;
treating that as an offset put them (and VIEW plots) at about twice the
coordinates. One shared `named_view_center` now resolves the centre in
f64 (DVec3/DQuat), taking a centre equal to a non-zero target as the old
convention; VIEW RESTORE, the view plot window and Place on Sheet use it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 09:29:22 +03:00
Hakan Seven 078306d8fc Merge pull request #1613 from ramox81/codex/sheet-set-manager
Sheet Set Manager, NEWSHEETSET / OPENSHEETSET and sheet set fields
2026-10-06 09:17:20 +03:00
Hakan Seven 6da9675c55 Merge pull request #1614 from ramox81/codex/count-feature
Count: COUNT / COUNTAREA count mode, Count palette, count fields and tables
2026-10-06 09:16:57 +03:00
ramox81andClaude Opus 5.5 7ad6e5b094 Count: Invalid Area dialog, table block kept with the table
- When the count area's boundary is gone the approved Invalid Area dialog
  asks: undo the change (also its X and Cancel) or count all of model space;
  "always" keeps the choice in the settings. An edited boundary moves the area.
- A table's *T block is brought up to date whenever the table changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 15:40:02 +03:00
ramox81andClaude Opus 5.5 0d0fbafaa8 Sheet sets: Place on Sheet, sheet view menus, block lists, missing status, field refresh
Model Views lists named model views and places them on the current sheet
(xref, viewport, paper-space named view, view label with navigation
fields, sheet view record); sheet view rows get Display, Rename & Renumber
View, Set category, Place Callout Block and Place View Label Block; the
View Category dialog's Add Blocks opens List of Blocks / Select Block; a
sheet whose relative path is gone shows missing; sheet set fields store
their values when a set changes; named views keep their centre relative to
the target. Codec pin moves to the revision with these field helpers.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 15:13:33 +03:00
ramox81andClaude Opus 5.5 95559a97f3 fix(save): keep a loaded solid's own wireframe cache
Saving filled every 3D solid without stored wires with tessellated display
edges, so solids read from a file without a wireframe cache (for example a
DXF) were saved with edges OCS never created. Only solids without ACIS data
now get an edge cache on save; solids OCS creates or edits already get their
wires when they are built.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 14:35:32 +03:00
ramox81andClaude Opus 5.5 5c9f19a4dc Sheet sets: import statuses, view navigation fields, drawing lock files
Import Layouts as Sheets shows the reference's statuses (already part of
a sheet set / may belong to another sheet set / available) and Browse
replaces the list; the Field dialog SheetView tree lists sheet views with
their properties, scale formats and hyperlinks; drawings open in tabs get
.dwl/.dwl2 lock files that other instances read as open; the codec pin
moves to the revision with sheet views and the default output folder.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 13:08:37 +03:00
ramox81andClaude Opus 5.5 0a26709d13 Count: measured messages and listing, groups, Current area, boundary checks, fills and solids recoloured
- COUNTCOLOR / COUNTERRORCOLOR / COUNTSERVICE reject any other value with
  the range message; COUNTTABLE ? lists in the reference order, padded,
  22 lines a page with Press ENTER to continue:, then the totals.
- Target picks report N found / N found, M total; several objects (or one
  that is not a block reference) count their copies, shown as Geometries
  in the palette.
- Current area is the area in use (kept aside by Entire model space),
  otherwise all of model space; an invalid Object boundary ends with the
  reference message.
- Count colours reach solids and fills; the palette list and the count
  are recomputed only when the drawing changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 11:36:24 +03:00
ramox81 88d8a33572 Merge remote-tracking branch 'origin/main' into codex/count-feature
# Conflicts:
#	Cargo.lock
#	src/app/commands/field.rs
#	src/app/control/actions.rs
#	src/ui/window/field_dialog.rs
2026-10-05 09:21:43 +03:00
ramox81 1696316e1f Merge remote-tracking branch 'origin/main' into codex/sheet-set-manager
# Conflicts:
#	Cargo.lock
#	src/app/control/actions.rs
#	src/ui/window/field_dialog.rs
2026-10-05 09:20:40 +03:00
ramox81andClaude Opus 5.5 0e1e13e524 WIP: Sheet Set Manager palette, wizard, properties and sheet set fields
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 09:10:17 +03:00
Hakan SevenandClaude Opus 5.5 ba8aed4fad fix(dynmode): one toggle keeps DYNMODE's sign in step
F12, the drafting dialog and restored settings each re-derived DYNMODE and
lost the mode on the way: F12 off set 0, so on came back as 3 even after
DYNMODE 1. set_dyn_input now makes off negative (temporarily off) and on
restore the stored mode, and the bare query prints the stored value.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-03 15:01:45 +03:00
yztink c9d9f9c2bb feat(sysvar): add DYNMODE system variable and command for Dynamic Input 2026-10-02 21:01:02 -07:00
ramox81 e29b408bda WIP count feature 2026-10-02 17:52:13 +03:00
ramox81andClaude Opus 5.5 785db5683b feat(field): table formula buttons, block placeholders, attribute fields on insert, plot-time field stamping
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 17:22:08 +03:00
Hakan Seven 0de1e91f99 Merge PR #1585 from ramox81/codex/field-command: FIELD command and Field dialog; attribute definition field buttons
The PR pinned the codec to its fork through [patch]; codec #75 is merged
upstream and main already points at it, so the patch section is dropped.
The two windows-sys features it adds (Globalization, Identity) stay.
2026-10-02 14:14:15 +03:00
ramox81andClaude Opus 5.5 f6f2b81441 feat(field): FIELDDISPLAY gray field background (screen only, profile setting)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 11:20:02 +03:00
PanosandClaude Opus 5 9fe2e4fa58 fix(view): hold ZOOMFACTOR to its own range, finish the exponential zoom
The exponential camera step is the right call. `0.9 ^ delta` is strictly
positive for every real delta, in and out cancel exactly where the
subtraction lost a percent of the view on every round trip, and the file's
own header has promised an "exponential feel" since it was written. Three
surfaces were left behind it, and the wider range exposed a fourth thing.

The range of the system variable. 3 to 100 is the range ZOOMFACTOR has, and
the User Preferences page was built against it; `SETVAR ZOOMFACTOR` accepts
that and nothing else again. A faster wheel is the Options window's business
instead: the slider covers the variable's own range, the field beside it
reaches 500, and a read-out says what a notch actually does ("10.0% a
notch") so the number being set is readable rather than implied. A value
above 100 therefore lives only in this application's own configuration file,
where it is nobody else's to read, and a bare `SETVAR ZOOMFACTOR` still
reports it. The bounds and the clamp live in one place now
(`settings::clamp_zoom_factor`): four literal copies of `3, 100` are what
let a surface be missed in the first place.

A floating viewport in MSPACE. It zooms its own view through
`zoom_active_viewport`, which kept subtracting: the factor reached zero at
6.67 steps, so from ZOOMFACTOR 360 up every notch inside a viewport bottomed
out on the clamp — a tenfold jump a notch, and the top third of the slider
doing nothing at all. Exponential there too, from a base of 0.85 so the
default notch still moves a viewport the 15% it always has. Each surface
keeps its own long-standing feel rather than inheriting the other's.

The trackpad pinch. `pinch_zoom_steps` was calibrated against the
subtraction (`1 - step / 10 = 1 / (1 + m)`) so that a pinch of m leaves the
view exactly 1 + m times closer — the property docs/trackpad.md documents
and the reason the gesture tracks the fingers at all. Inverting the zoom law
by hand is what let the two drift apart, so the step is asked of the camera
now (`Camera::zoom_steps_for_ratio`), which cannot drift by construction.
`pinch_is_one_to_one` recomputed the old formula rather than the camera's,
so it kept passing through all of this; it zooms a real camera and measures
the distance it lands at instead.

Also: `zoom` had a floor and no ceiling, and zooming out multiplies. At
ZOOMFACTOR 500 a notch out is x2.4, so about ninety notches — a couple of
seconds of scrolling — ran the distance past what an f32 far plane
(`distance * 1000`) can hold, and the viewport went black on an infinite
projection. A degenerate pinch magnification of -1 or beyond reached the
same place through the other side. Both are bounded now.

Also: two doc comments quoted the linear law (`zoom_view_at_cursor` and the
one on `pinch_zoom_steps`), and docs/trackpad.md stated the pinch identity
and claimed the tests covered it against the camera. All updated, with what
a notch does and where each surface's range comes from written down.

Tests, each confirmed against the behaviour it describes: the zoom law at
every factor the application can hold (positive, monotonic in the setting,
in and out cancelling), the ceiling under a long scroll out in both
projections, the published inverse and what it does with a nonsense ratio,
the viewport factor and a real viewport zoomed three notches at the top of
the range, the SETVAR range including a value the Options field set, the
Options field (above 100, above the ceiling, cleared, not a number), its
agreement with the slider, Close putting both the value and the field back,
and the read-out's percentages. 1882 lib tests pass.

The two new Options strings are not in the locale catalog yet, so they
render in English until it is regenerated.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 10:51:26 +03:00
ramox81 762cf1e7e4 Merge remote-tracking branch 'origin/main' into codex/field-command
# Conflicts:
#	src/ui/window/attdef_dialog.rs
2026-10-02 10:46:53 +03:00
ramox81andClaude Opus 5.5 efbb1797cd ATTDEF: the dialog's Specify on-screen choice is kept with the user settings
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 10:39:18 +03:00
Hakan Seven 7a6908c7ca Merge PR #1573 from ramox81/codex/blocks-palette-parity: Blocks palette tabs, insertion options, drag insertion and -INSERT 2026-10-02 10:10:51 +03:00
Hakan Seven c7df841711 Merge PR #1584 from yztink/fix/scr-scripts: support .scr scripts, multi-line and single-line formats, and command prefixes 2026-10-02 10:00:01 +03:00
yztink f32d0422d2 fix(script): support AutoCAD .scr scripts with multi-line, single-line, and prefix handling 2026-10-01 23:34:15 -07:00
F4brizi e131843826 feat(viewport): expand ZOOMFACTOR range to 500 2026-10-01 18:49:23 -03:00
ramox81andClaude Opus 5.5 0826101c5e Blocks palette: tabs, options, drag insertion and -INSERT
Rebuild the Blocks palette with Current Drawing / Recent / Favorites /
Libraries tabs, wildcard filter, six views, insertion options, click and
drop insertion and a block context menu. INSERT opens the palette, the
new -INSERT runs on the command line, the ribbon Insert button becomes a
block gallery, and BLOCKMRULIST, BLOCKREDEFINEMODE, BLOCKNAVIGATE,
BLOCKSTATE, EXPLMODE and INSNAME are added.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 11:17:38 +03:00
Karim Jerbi 3345b6453e fix(background): keep the app alive when a background worker panics
Bug:
background_task joined the worker thread with .expect(...). Any panic
inside a background closure (decoding a malformed file, an unexpected
None) was re-raised on the main thread and took the whole application
down, even though the worker's failure was already contained.

Reproduce:
1. Run an operation that executes in a background worker, e.g. loading
   or converting a deliberately corrupted file whose decoder panics.
2. Before: the process dies with the worker's panic message.
3. After: the command line shows "background task failed: <label> -
   <panic>" and the application keeps running.

Fix:
The worker closure is wrapped in catch_unwind; a panic is converted to
Message::BackgroundTaskFailed(context, message) delivered back to the
update loop and surfaced as a command-line error. Each call site passes
a context label naming the operation. A failed thread join (thread
aborted) is handled the same way instead of expect().
2026-09-30 19:15:49 +01:00
Karim Jerbi 2d6f4fcfdf fix(tabs): close by stable document id instead of vector index
Bug:
Message::TabClose carried a vector index captured when the view message
was built. Closing several tabs in one batch (Close All / Close Others
with unsaved-changes dialogs, or a queue of continuation updates) let an
earlier close shift the vector before a later TabClose(idx) was handled:
self.tabs.remove(idx) either panicked (index past the end) or closed a
different tab than the one the user confirmed.

Reproduce:
1. Open several drawings and modify each so they all prompt on close.
2. Use Close All, or close two tabs in quick succession so both messages
   are handled in one batch.
3. Before: panic in remove(idx), or the wrong tab closes while the tab
   the user chose stays open (or its work is lost).
4. After: the chosen tab closes; an id already closed by an earlier
   message is a no-op.

Fix:
TabClose now carries the tab's stable u64 id, resolved to a vector
position when the message is handled, not when it is built;
PendingClose::Tab stores ids the same way. All construction sites pass
tab.id (a raw usize index no longer type-checks), and
DocTabCloseAll/DocTabCloseOthers build their queues from live ids at
handling time. A missing id means the tab is already gone, so the
handler returns Task::none().
2026-09-30 19:15:49 +01:00
Hakan SevenandClaude Opus 5.5 d70cc46712 fix(web): STEP export no longer panics; STEP/STL exports download in the browser
The STEP header timestamp used SystemTime, which panics on wasm, and the
exports wrote through std::fs, which the browser does not have.

Fixes #761

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 19:18:53 +03:00
Hakan SevenandClaude Opus 5.5 38fe2b0b08 fix(plot): text and leader background masks plot paper-white, not black
The mask is filled with the canvas colour; plotting carried that dark
colour (or the light-to-black rule) onto the sheet.

Fixes #1072

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 19:01:56 +03:00
Hakan Seven 1a7e372f24 Merge pull request #1517 from mechpanos/fix/windows-printer-properties-freeze
fix(print): open the driver's printing preferences without blocking the event loop
2026-09-28 17:27:32 +03:00
mechpanosandClaude Opus 5 9ba2493027 fix(print): open the driver's printing preferences without blocking the event loop
Properties… in the Plot dialog froze the application on Windows.

`on_printer_properties` called `DocumentPropertiesW` with `DM_IN_PROMPT`
from inside the closure handed to `iced::window::run`, and iced runs that
closure synchronously on the winit event-loop thread. The driver's
property sheet wants to run its own modal message loop on that same
thread, so the two loops collide: the sheet is never created at all, the
window stops painting, and the thread spins at 100% of one core with no
way back.

Measured on Windows 11 x86-64: the pinned thread is the window's own UI
thread, and compstui.dll plus the driver's PrintConfig.dll are loaded
into the process, so execution does reach the driver's property-sheet
code and never leaves it. It reproduces with a physical printer as
readily as with Microsoft Print to PDF, so the mechanism was broken for
every printer, not only the virtual one named in the report.

The system's own printing-preferences UI is now started as a separate
process, which pumps its own messages and leaves ours free, so the
freeze is impossible by construction rather than merely unlikely. The
command that does it already existed for the case where no printer is
selected; it now serves a named printer too, and the in-process modal
path is gone. Preferences still reach the job: the sheet writes the
per-user DEVMODE that the plot path reads back through
`DocumentPropertiesW`, which was confirmed by changing the orientation
in the sheet and watching the value the plot path reads change with it.

The new test pins down that the printer name must reach `printui` as a
single argument: split across several it matches nothing and the process
exits 0 without drawing anything, which would be a failure with nothing
to show the user.

Fixes #1474

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 15:40:39 +03:00