Finder thumbnails and "Open with" registration fail in the field for
three compounding reasons: the app claims com.autodesk.dwg/.dxf but
never declares them (UTImportedTypeDeclarations was missing, so on
systems with no other declarer Launch Services can't bind the
extensions at all); the QuickLook appex only serves com.autodesk.dwg
while machines with AutoCAD installed resolve .dwg to its exported
com.autodesk.autocad.dwg (BricsCAD etc. likewise win with their own
UTIs); and the ad-hoc --deep signature carries no entitlements, but a
QuickLook thumbnail extension must be sandboxed
(com.apple.security.app-sandbox) before macOS will run it.
Import-declare both UTIs, claim and serve the AutoCAD variants too,
add the appex sandbox entitlements, and add
packaging/build_macos_signed.sh — a local mirror of the CI build-macos
job that signs with a Developer ID (hardened runtime, per-component
entitlements), notarizes and staples. DEVELOPER_ID=- reproduces the
CI ad-hoc build.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The AppImage ships both the .desktop file and the hicolor icon, yet the dock
button came up blank on Wayland. A Wayland compositor has no StartupWMClass to
key on — it matches a window's app_id against the basename of an installed
.desktop file to find its icon — and iced defaults window app_id to an empty
string, which OCS never overrode, so nothing matched.
Set application_id to the reverse-DNS id the .desktop is installed under,
reusing the existing file_association::APP_ID const rather than a second copy.
iced enables both the x11 and wayland winit backends by default and feeds the
same application_id to each: on Wayland it is the app_id, on X11 it becomes
WM_CLASS. So this also changes the X11 WM_CLASS, and the old
StartupWMClass=OpenCADStudio would no longer match — realign it to the same id
so X11 keeps working too.
Confirmed on COSMIC/Wayland: the dock icon now appears. This is the Linux half
of the same class of bug as the Windows taskbar report (#392, still open): the
window not carrying the identity the OS needs to find its packaged icon.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Double-clicking a drawing started a whole second copy of the app. Now it
lands as a tab in the editor already open, and that window comes forward.
The election is the bind itself: every GUI launch tries a deterministic
per-user loopback port, and the OS grants it to exactly one process and
releases it on any death, SIGKILL included. Nothing to reap, no PID to
probe, no stale lock after a crash. The winner serves the port from an
iced subscription; the loser checks it is talking to a matching editor,
hands the paths over and exits. Every surprise — no answer, a stranger on
the port, a timeout — boots a normal window, i.e. the old behaviour: the
feature can degrade, but it cannot lose the file.
The gate in main is positional, after every headless mode has returned.
The plugin runner is this same binary re-spawning itself, so a flag list
would rot the first time a mode is added; a position cannot.
Handing a drawing over that is already open switches to its tab instead
of loading a second copy, comparing resolved paths so a symlink or a
`..` hop is still recognised as the same file.
`opening` is a single slot that a second open would overwrite, and
on_file_opened drops any result arriving once it is clear — so drawings
handed over at once would silently vanish. They queue in pending_opens,
drained from every path that clears the slot, error and cancel included.
Exec becomes %F so one launch takes the whole selection; the CLI takes a
list and boot fans it out through the same door. --new-instance forces a
separate process; --read-only / --script / --new always get their own.
Not reused: the automation server. It dispatches arbitrary commands and
writes arbitrary paths, and its open replaces the active tab's document
in place — publishing that on a port every local process can reach would
be unforced privilege escalation. Only its JSON-lines framing is shared.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round-trip a raster preview through the DWG's embedded preview slot and
surface it to the OS file managers, so drawings show their contents in
Explorer / Finder / Nautilus instead of a generic document icon.
OCS:
* io::thumbnail — rasterize the scene to a BMP DIB on save (embedded via
acadrust's new Preview type) and read it back on open for the Start
page recent list; `--dwg-thumbnail IN OUT SIZE` CLI extracts a badged
PNG for external thumbnailers.
* io::file_association::install_thumbnailer — self-install the OS
integration on startup: Linux writes a .thumbnailer + hicolor mimetype
icons; Windows registers the IThumbnailProvider DLL under HKCU.
Shared core:
* crates/dwg-thumbnailer — lean (image-only) preview extractor + the
`badge_dwg` full-width "DWG" band, used by every platform so the
ribbon is single-sourced. Ships an rlib+staticlib.
* crates/dwg-thumbnailer-win — IThumbnailProvider COM in-proc server
(cfg(windows), CI-built as a workspace member).
* macos/ — QuickLook thumbnail extension (Swift + C-ABI bridge to the
core staticlib), assembled into a .appex.
Icons & packaging (single SVG source -> per-platform assets in CI):
* assets/mimetypes/image-vnd.{dwg,dxf}.svg — themed file icons.
* packaging: WiX ships dwg/dxf.ico + the thumbnail DLL and points the
ProgIds at them; Info.plist gets CFBundleTypeIconFile + the QuickLook
extension in Contents/PlugIns.
* release.yml — generate .ico (Windows) and .icns (macOS) from the SVGs,
build the QuickLook .appex, and bundle everything.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Windows installer:
- Optional Desktop shortcut feature (default on, deselectable) via a switch to
the WixUI_FeatureTree UI.
- Refresh the shell after install (ie4uinit -show) so .dwg/.dxf icons and
associations appear without a reboot.
- Tidy the Add/Remove Programs entry: ARPNOREPAIR plus contact/update/comments
metadata (Modify stays enabled for the feature tree).
Release workflow:
- Publish SHA256 sidecars for the AppImage, portable .exe, MSI and .dmg.
Linux:
- Ship an AppStream metainfo.xml for software-centre integration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
WixUI_Minimal fell back to WiX's built-in placeholder (Lorem ipsum)
RTF because no WixUILicenseRtf was set. Ship License.rtf generated
from the repo GPL-3 LICENSE and point the variable at it via a new
-dLicense candle arg.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
candle rejects RegistryValue/@Name='' — the DefaultIcon and
shell\open\command rows must write the key's default value by
omitting Name entirely. Empty Name broke the MSI build.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both the MSI and the portable build were missing Applications\OpenCADStudio.exe\
DefaultIcon, causing a blank generic icon in the "Open with" context-menu list
and the "Choose another app" picker.
- packaging/windows/main.wxs: add Applications\OpenCADStudio.exe\DefaultIcon
(+ FriendlyAppName, shell\open\command, SupportedTypes) to the
DefaultPrograms component for MSI installs (HKLM).
- src/io/file_association.rs: add DefaultIcon to the Applications\
OpenCADStudio.exe block written at runtime for portable builds (HKCU).
https://claude.ai/code/session_01DFVSKgViFaxEjZD2KsTdtt
Adds a DefaultPrograms component publishing Capabilities and a
RegisteredApplications entry under HKLM. This makes Open CAD Studio
appear in Settings > Default Apps and the shell "Open with" list, so
users can set it as the default handler for .dwg and .dxf files.
Modern Windows guards the actual default behind a per-user UserChoice
hash that an installer cannot forge, so this is the supported path to
becoming the default rather than silently overwriting the association.
https://claude.ai/code/session_01DFVSKgViFaxEjZD2KsTdtt
Moves the WixUI_Minimal UI and finish-screen launch checkbox out of
main.wxs into a dedicated ui.wxs fragment, referenced from main.wxs via
<UIRef Id='OpenCADStudioUI'>. Keeps the package/feature definition and
the UI concerns in separate files.
Updates the release workflow to compile both .wxs files (candle now
writes per-source .wixobj into a directory) and link both objects.
https://claude.ai/code/session_01DFVSKgViFaxEjZD2KsTdtt
Adds WixUI_Minimal UI to the WiX installer so users see a proper
Welcome → Progress → Finish wizard. The finish screen includes a
pre-ticked "Launch Open CAD Studio" checkbox; clicking Finish with
it checked starts the application immediately after the installer closes.
Also updates the light.exe invocation in release.yml to include
-ext WixUIExtension, which is required to link the WixUI dialogs.
https://claude.ai/code/session_01DFVSKgViFaxEjZD2KsTdtt
- release.yml: ad-hoc codesign the .app before packaging so a quarantined
download avoids the "app is damaged" Gatekeeper verdict; emit the cask
version + sha256 to the job summary each release for easy tap bumps.
- packaging/homebrew: Homebrew cask + tap/usage notes; install via
--no-quarantine (the actual Gatekeeper bypass for an unsigned app).
- README: split macOS install into Homebrew and manual .dmg paths with
the xattr / Settings "Open Anyway" fallbacks.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A single ProgID with two `<Extension>` children, each carrying its own
`<Verb Id='open'>`, makes WiX emit two rows with the same Registry
primary key and light fails with LGHT0130. Split into one ProgID per
extension (`OpenCADStudio.DWG`, `OpenCADStudio.DXF`); both still invoke
the same exe with the file as `argv[1]`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Cross-platform prerequisite for OS-level file associations: the boot
task now consumes `std::env::args_os().nth(1)` as a path and dispatches
`Message::OpenRecent` for it. Flag-style args (starting with `-`) are
ignored, and `OpenRecent` already does the file-existence check, so a
bogus path lands as a clean command-line error instead of a panic.
Linux: the AppImage's desktop entry adds `image/vnd.dwg` alongside the
existing `image/vnd.dxf` MIME type and grows a `%f` placeholder in
`Exec=` so the launcher forwards the picked file path. Once the
AppImage is integrated with the system (xdg-mime / AppImageLauncher),
double-clicking a .dwg / .dxf opens it in Open CAD Studio.
Windows: new `packaging/windows/main.wxs` defines an MSI installer —
per-machine install to `Program Files\Open CAD Studio`, Start Menu
shortcut, `MajorUpgrade` so newer MSIs replace older ones, and a
single ProgID `OpenCADStudio.Drawing` that owns both `.dwg` and
`.dxf` and launches the exe with the file as `argv[1]`. The icon is
pulled from the SVG logo, converted to multi-resolution ICO at build
time with the runner's pre-installed ImageMagick. CI now also runs
`candle` / `light` (WiX Toolset 3, pre-installed on `windows-latest`)
and uploads both the bare `.exe` (portable) and `.msi` (installer)
to the release.
macOS Info.plist already declares the DWG / DXF UTIs; combined with
the argv-handling change above, double-clicking a drawing in Finder
will open it in Open CAD Studio without further packaging changes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Joining the OpenAEC Foundation (open-aec.com). Crate/struct become
OpenCADStudio, user-facing strings use the spaced "Open CAD Studio"
form, repo URLs point to HakanSeven12/open-cad-studio. Logo (window
icon + assets/logo.svg) redrawn with OCS initials. Drop examples/
binaries — unused.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- .github/workflows/release.yml: remove the build-flatpak job; matrix-
add macOS (arm64 + x86_64) that builds H7CAD.app by hand, renders
.icns from assets/logo.svg via librsvg + iconutil, and packages a
UDZO .dmg. AppImage path updated to packaging/H7CAD.desktop.
- packaging/H7CAD.desktop: moved out of flatpak/ so the AppImage job
doesn't depend on a Flatpak layout.
- packaging/Info.plist: macOS bundle template; __VERSION__ swapped
for the release tag at build time.
- flatpak/: deleted (manifests, metainfo, desktop, builder cache).
- src/main.rs: `#![cfg_attr(all(windows, not(debug_assertions)),
windows_subsystem = "windows")]` so the Windows GUI binary no
longer spawns a console window alongside it (debug builds keep
the console for log output).
- README: add macOS install section, document Gatekeeper / SmartScreen
on first launch since the binaries are unsigned.
Bump to 0.3.5.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>