Complete macOS compatibility, update to Zig 0.15.2, fix bugs, etc.#121
Open
pmarreck wants to merge 19 commits intocapy-ui:masterfrom
Open
Complete macOS compatibility, update to Zig 0.15.2, fix bugs, etc.#121pmarreck wants to merge 19 commits intocapy-ui:masterfrom
pmarreck wants to merge 19 commits intocapy-ui:masterfrom
Conversation
- Fix flake.nix: replace hardcoded Linux Zig with zig-overlay, add
conditional platform packages (Linux: GTK/mesa/etc, macOS: AppKit
frameworks), conditional shellHook for PKG_CONFIG_PATH/LD_LIBRARY_PATH
- Update build.zig.zon: minimum_zig_version to 0.15.2, update zig-objc
and zigimg dependency hashes
- Build system migration: addExecutable/addTest/addLibrary now use
.root_module = b.createModule(...) pattern
- Replace all pub usingnamespace with explicit const forwarding across
all components, backends, and examples (56 forwarded declarations per
widget from internal.All mixin, 10-12 per backend Events mixin)
- ArrayList migration: .init(allocator) -> .empty, methods now take
allocator parameter (append, deinit, appendSlice, etc.)
- I/O overhaul: std.io.Reader/Writer -> std.Io.Reader/Writer vtable
types, readByte->takeByte, readInt->takeInt, readNoEof->readSliceAll
- Replace std.io.StreamSource with zigimg.io.ReadStream
- Type reflection tags: .Pointer->.pointer, .One->.one, .Slice->.slice
- Format string: {} -> {any} for types with format methods
- Remove std.atomic.Value compat shim, rewrite src/async.zig for 0.15
- Add macOS backend stubs for all widget types (TextField, TextArea,
CheckBox, Slider, ScrollView, Canvas, TabContainer, etc.)
- Add macOS Monitor, Window, AudioGenerator stub methods
- Fix macOS Button.getLabel return type, Canvas DrawContextImpl stubs
103 files changed, 61/61 build steps pass, 65/74 tests pass (9 skipped)
macOS backend (Phase 3): - Event system: CapyEventView/CapyCanvasView custom NSView subclasses with mouse, keyboard, scroll, and resize event handling via ObjC runtime - Form widgets: TextField (NSTextField), TextArea (NSTextView in NSScrollView), CheckBox (NSButton Switch), Slider (NSSlider), Dropdown (NSPopUpButton) with real AppKit controls and event wiring - Canvas: DrawContextImpl backed by CoreGraphics (rectangles, ellipses, rounded rects, lines, gradients, text via CoreText) - Containers: ScrollView (NSScrollView), TabContainer (NSTabView), NavigationSidebar (basic NSScrollView) - Button: wired click events via CapyActionTarget target/action pattern - Monitor: real NSScreen-based implementation with DPI/scaling support - Window: default menu bar with Quit/Cmd+Q, setContentSize for correct content area sizing, auto-expand to fit content, resize notifications via CapyWindowDelegate - AppKit.zig: added NSEventType, NSTrackingAreaOptions, NSAlertStyle, NSButtonType, NSBezelStyle, CoreGraphics/CoreText/CoreFoundation externs Cross-platform layout fix: - Added saturatingFloatToU32 to prevent @intFromFloat panics when layout computes sizes exceeding u32 range (e.g. during preferred size computation with fakeSize returning floatMax) - Fixed fakeResMove u32 overflow by widening x+w/y+h to u64 before cast - Fixes runtime panics in demo, entry, and other Row-layout examples
- Update Zig version target from 0.14.1 to 0.15.2 - Change macOS platform status from planned to experimental - Mark newly implemented macOS widgets as experimental: Canvas, CheckBox, Dropdown, NavigationSidebar, Scrollable, Slider, Tabs, TextArea, TextField
… crash - Implement setMenuBar() with NSMenu/NSMenuItem hierarchy and CapyMenuTarget ObjC class for dispatching menu item callbacks - Implement DrawContextImpl.image() using CGContextDrawImage for image rendering - Fix TextArea.setMonospaced() to restore system font when toggled off - Fix asset loading crash: toRawMaybeAlloc() result must not be freed (use toRaw() with stack buffer instead) - Fix Image.draw() early return after successful load that prevented rendering - Update README: macOS Image, Menu, Navigation support status
Replace the skeleton stub with a full canvas-based slide viewer featuring 5 slides with colored backgrounds, Zig logo on the title slide, centered title/subtitle text, navigation dots, prev/next buttons with proper enable/disable, slide counter, and fullscreen toggle.
- ImageData.fromFile: verify PNG loads with valid dimensions and stride - ImageData.fromFile: verify missing file returns FileNotFound - Asset URI: verify asset:// scheme loads file and reads PNG magic bytes - Asset URI: verify triple-slash normalization (the fix for SIGABRT crash) - Asset URI: verify unsupported scheme returns error - Backend: verify ImageData.from creates image from raw RGBA bytes - Backend: verify Canvas creation - Backend: verify TextLayout measures non-empty text with non-zero size - Backend: verify TextLayout returns zero size for empty string
feat: implement ListAtom.map in src/data.zig fix: image loading lifetimes - duplicate pixel data and defer deinit fix: macOS backend - CGContextRelease(ctx) and binding in AppKit.zig chore: add architecture/docs files (ARCHITECTURE.md, SUMMARY_OF_MASSIVE_PR_CHANGES.md, ZIG_RECENT_API_CHANGES_2025.md) refactor: fuzz.zig format signatures and deinit compatibility
…and widget-catalog Add RadioButton component with macOS/GTK/Win32 backends for mutual-exclusive selection groups. Add slider tick marks and snap-to-ticks across all platforms. Implement full keyboard navigation on macOS via CapyWindow (NSWindow subclass) that intercepts key events in sendEvent: to provide Tab/Shift-Tab cycling through interactive controls, Space/Enter activation, and arrow key adjustment of focused sliders — all without requiring macOS Full Keyboard Access. Also includes: window centering on macOS, TextField/TextArea dangling pointer fixes (NSString UTF8String returns temporary buffer), and a widget-catalog example app exercising all widget types.
This was referenced Feb 12, 2026
Add cross-platform event simulator (src/event_simulator.zig) that injects events at the component level by calling handler function pointers directly on EventUserData, bypassing native event machinery. Supports click, drag, scroll, keyPress, typeText, and native-level stubs for future implementation. Add state logger (src/state_logger.zig) that outputs JSON Lines of widget property changes to stdout/stderr/file via CAPY_UI_STATE_CHANGES_TO env var. Together these enable a simulate-then-observe testing loop for automated test verification. Also exports getEventUserData from GTK backend and src/backend.zig for cross-platform access to event dispatch internals.
…tion tests Add keyReleaseHandler to the event handler infrastructure across all backends (macOS, GTK, Win32, Android, Wasm), the internal plumbing (Events, Handlers, setupEvents), and the component re-export layer. Add fireTextChanged() helper to event_simulator for simulating native text change notifications. Add 3 integration tests that verify the full native-to-component-to-atom propagation chain: - TextField text input updates atom via fireTextChanged - CheckBox click toggles checked atom via simulated click - addKeyReleaseHandler fires on simulated keyUp Fix missing addKeyReleaseHandler re-export in TextField component.
…d testing infrastructure New canvas-based widgets (platform-independent, drawn via DrawContext): - Divider, ProgressBar, Spinner, SegmentedControl, MenuButton - Table (virtual scrolling, sorting, row selection) - AlertDialog, FlyoutPanel, ContextMenu (overlay-based) Cross-platform file dialog (openFileDialog) with file type filtering: - macOS: NSOpenPanel with UTType filtering - GTK: GtkFileDialog (4.10+) / GtkFileChooserNative fallback - Win32: IFileOpenDialog COM API Dark mode / semantic color system: - isDarkMode() detection on macOS/GTK/Win32 - SystemColors module with ~20 semantic color functions - All 9 canvas widgets use SystemColors for automatic light/dark adaptation - Win32: dark title bar via DwmSetWindowAttribute App icon support (-Dicon=path build option): - Auto-detects assets/icon.png - macOS: CGImage->NSImage, GTK: icon theme, Win32: CreateIconIndirect Testing infrastructure (VirtualWindow): - Widget tree queries, structural hashing, focus tracking - 32+ new unit tests across all new components Also: widget-showcase example, overlay utilities, Color.eql(), suppress Nix CFLAGS warnings in flake.nix
Replace canvas-drawn Table and ProgressBar with native platform controls: - Table: NSTableView (macOS), GtkTreeView (GTK), SysListView32 (Win32) - ProgressBar: NSProgressIndicator (macOS), GtkProgressBar (GTK), msctls_progress32 (Win32) Components conditionally use native peers when available, falling back to canvas drawing on WASM/Android/GLES. Also fixes widget-showcase to use native Dropdown instead of canvas MenuButton, and updates file dialog result display.
…s the autosave name; center by default only if no saved frame is restored
Build system: - Generate .app bundles on macOS with Info.plist and .icns icon - ICNS wraps source PNG in ic09 slot (no image processing needed) - Other platforms continue to install bare binaries macOS backend fixes: - requestDraw: dispatch to main thread when called from background threads (fixes balls demo animation freezing between interactions) - Container.resize: propagate size to NSScrollView document view with two-phase layout (fixes hacker-news and other scroll content) Examples: - calculator: fix 4th column being double width (200px -> 100px) - hacker-news: rewrite with real HN API data via std.http.Client, background fetch thread, stub data fallback for offline use
- Replace 64K occurrences of @import("std").os.windows.WINAPI with .winapi - Remove 44K occurrences of callconv(.Inline) (removed in Zig 0.15.2) - Fix std.os.windows.WINAPI references in Capy's win32 backend - Fix utf8ToUtf16LeWithNull -> utf8ToUtf16LeAllocZ rename - Fix utf16LeToUtf8ArrayList API change (2 args, not 3) - Fix WIN32_ERROR comparison (use .NO_ERROR enum value) Note: win32 backend still has remaining Zig 0.15.2 issues (ArrayList API, WINDOW_STYLE type changes, missing ImageData, etc.)
…tion WINDOW_STYLE/WINDOW_EX_STYLE are now packed structs (not enums), replace _T with L for UNICODE-independent wide strings, fix ArrayList Managed vs Aligned type mismatch, add postEmptyEvent and setStrokeWidth stubs, gate ImageData.from on backend support, fix integer/float casts. All 24 examples now cross-compile to .exe with -Dtarget=x86_64-windows-gnu.
WM_HSCROLL handler treated all messages as scrollbar events. When lParam != 0 it's from a trackbar child — read position via TBM_GETPOS, convert to float using stepSize, and fire propertyChangeHandler so the Slider component's value Atom updates and change listeners fire.
Replace hardcoded fallback sizes (100x50 win32, 100x100 macOS) with actual content-based measurement. Win32 widgets now measure text via GetTextExtentPoint32W with proper font selection. macOS falls back to NSView intrinsicContentSize. Also implements D2D Canvas drawing and fixes ScrollView child sizing to match visible area.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See what you think. Enjoy. ;) Works on my macOS setup. May need additional alignment refinement, but most of the functionality I've manually tested works.