<feed xmlns='http://www.w3.org/2005/Atom'>
<title>pardes.git/src/macos/build-app.sh, branch release-0.24</title>
<subtitle>Pardes</subtitle>
<id>https://git.0x4200.cafe/pardes.git/atom?h=release-0.24</id>
<link rel='self' href='https://git.0x4200.cafe/pardes.git/atom?h=release-0.24'/>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/'/>
<updated>2026-08-11T12:58:59Z</updated>
<entry>
<title>macos: pixel attachments, live theming, and a signed app</title>
<updated>2026-08-11T12:58:59Z</updated>
<author>
<name>Gabriel Schneider</name>
<email>gbrls@0x4200.cafe</email>
</author>
<published>2026-08-10T20:23:18Z</published>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/commit/?id=a797a1ab2f648e773f7a1b28d12bf9441b9f13f4'/>
<id>urn:sha1:a797a1ab2f648e773f7a1b28d12bf9441b9f13f4</id>
<content type='text'>
The AppKit shell now draws what the core renders, follows the theme without a
relaunch, and builds into something you can hand to someone.

- Pixel attachments. Surface.images was dropped on the floor here, so a PDF
  pane showed nothing at all: native_images is now set, pardes_image_s carries
  the geometry the core already clipped, and PardesView keeps one CGImage per
  (serial, page, revision) so scrolling costs a draw and not a decode. Image
  panes get real pixels instead of the petscii fallback.

- Themes take hold live. pardes_tick never advanced the chrome animation, so
  every tagline kept the previous theme's colours until the next launch and
  the 16 ms re-pump spun for the rest of the session. pardes_theme_bg retires
  the hand-agreed #121212 and drives the window background and the titlebar
  appearance; a theme with no background of its own now gets a transparent
  window over an NSVisualEffectView.

- The cell snaps to whole DEVICE pixels rather than whole points. Monaco
  advances 8.4014pt at 14, so ceiling to 9 spaced every column 7.1% wider than
  the face was drawn for.

- The dial is one notch per 10 degrees instead of 20, and a release keeps
  turning in proportion to how hard it was thrown -- ramping up from zero at
  the floor, so a slow twist coasts not a little but not at all.

- A file dropped on the grid is a click plus Look, so it opens beside the pane
  it was dropped on. No drop concept was added to the core.

- The titlebar follows the focused pane: proxy icon, filename, and the dirty
  dot. File.saved_revision is the watermark that last one needed.

- Config (SPC f c) prints the resolved startup config path.

- build.zig assembles, signs and packages the bundle itself; build-app.sh is
  gone. -Dmacos-identity= takes a Developer ID, macos-dmg makes the image, and
  the icon is Glenda.
</content>
</entry>
<entry>
<title>macos: the AppKit shell, its icon, and the offscreen e2e harness</title>
<updated>2026-08-11T12:58:59Z</updated>
<author>
<name>Gabriel Schneider</name>
<email>gbrls@0x4200.cafe</email>
</author>
<published>2026-08-10T12:58:31Z</published>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/commit/?id=eb11ab331b4e13e2b9e5a673a4c012d22fdd1d9c'/>
<id>urn:sha1:eb11ab331b4e13e2b9e5a673a4c012d22fdd1d9c</id>
<content type='text'>
</content>
</entry>
<entry>
<title>a native macOS backend: libpardes plus an AppKit shell</title>
<updated>2026-08-10T12:17:07Z</updated>
<author>
<name>Gabriel Schneider</name>
<email>gbrls@0x4200.cafe</email>
</author>
<published>2026-08-08T13:44:56Z</published>
<link rel='alternate' type='text/html' href='https://git.0x4200.cafe/pardes.git/commit/?id=c3c8bbd8d8add99088c774c54bc1acf1e39ec895'/>
<id>urn:sha1:c3c8bbd8d8add99088c774c54bc1acf1e39ec895</id>
<content type='text'>
Adds -Dplatform=macos, a fourth backend beside tty, gui and web. Zig keeps the
core, the ptys, every effect and the worker threads; Swift owns NSApplication,
the window, input translation, and drawing the cell grid with CoreText. They
meet at a hand-written C ABI in src/macos/pardes.h, built as a static library
the app links.

The ABI is src/web.zig's boundary with the wasm removed, because both hosts are
the same animal: someone else owns the clock, feeds events in through flat
functions, and reads one packed cell buffer out. The browser proved the shape.
The one divergence is that the browser has no processes and forwards every
effect to JavaScript, whereas forkpty is right here, so src/macos.zig performs
them — spawn, write, resize_pty, save_file, new_file, write_dump, open_link,
set_clipboard. lsp, pipe and watch are answered with nothing and marked; the
core already tolerates that, since the browser answers none of them either.

This deliberately inverts ghostty's split, which was studied first and is
written up in docs/ghostty-macos-notes.md. Ghostty hands Zig a bare NSView*,
installs its own CALayer and owns the frame clock; Swift never renders. Pardes
does the opposite because its frame is already a cell grid and CoreText draws
one natively — the alternative is a second hand-rolled glyph atlas, which is
what most of gui.zig's 4,300 lines already are. It would also have been written
blind: the Swift half cannot be compiled here.

What makes the scaffold verifiable rather than dead code is that the Zig half is
ordinary POSIX and builds and tests on Linux. Borrowing ghostty's best trick,
build.zig translate-C's the header into the test build and src/macos.zig asserts
every constant, struct layout, and exported function's arity and widths against
it. That guard earned its place immediately: pardes_scroll grew a cell
coordinate after the Swift view had been written against the older form.

Skipped, and named as the upgrade path in docs/macos.md: the Xcode project,
xcframework, lipo and codesigning ghostty needs. All four exist for
distribution; a dev build is a swiftc invocation and a directory with a plist.

The Swift app is a scaffold and says so — every uncertain API spelling carries
an UNVERIFIED marker, and no part of it has been compiled.

tty is unaffected: 75/75 snapshot scripts and both unit suites pass.
</content>
</entry>
</feed>
