Skip to content

Latest commit

 

History

History
141 lines (132 loc) · 8.49 KB

File metadata and controls

141 lines (132 loc) · 8.49 KB

macOS Platform Notes

The macOS host core uses wzzc-dev/window/macos for AppKit windows, lifecycle, events, services, text-input session synchronization, renderer resize calls, and redraw requests. It creates an opaque HostSurface with an NSImageView CPU presenter, opaque native surface/display handles, and a HostImageSource. The application supplies ordered providers from moui_skia_renderer, moui_sun_renderer, or moui_wgpu_renderer; backend/macos never imports or constructs those renderers. macOS native WebView support uses WKWebView as a host platform view attached to the window content view. backend/macos reports native WebView available when the WebKit-backed stub is linked, syncs placements from DrawFrame.platform_views, forwards validated WebViewEvent values through the composition root, and drains WebViewController tasks after frame rendering. Page communication uses the versioned JSON Bridge; raw JavaScript evaluation is not part of the public API. For the full-window WebView/modal route, the active Skia presenter stays above WKWebView and full-surface platform-view frames clear it transparently. Both the GPU CAMetalLayer host view and CPU raster image view pass hit testing through to WKWebView without an overlay. While DrawFrame.overlay_bounds is present, the presenter routes input to MoUI and WKWebView excludes those bounds from hit testing. Modal transitions therefore do not reorder or reattach WKWebView's remote layer. Partial platform-view frames remain opaque white. This is deliberately limited to modal MoUI composition over a full-window native WebView rather than arbitrary native-view interleaving. The macOS WebView also reserves the first 32 logical points as a drag region. The host injects a small document-end script that reports top-bar rectangles for links, buttons, form controls, editable elements, and explicit data-moui-no-drag elements. Those rectangles remain clickable; blank points in the same strip call AppKit's performWindowDragWithEvent:. This keeps a web-owned title bar interactive without adding a native shell overlay. Window events pass through the shared backend conversion helpers, and the native host never imports moui_wgpu_renderer, moui_skia_renderer, wgpu_mbt, or moui_skia. The macOS service bridge routes text clipboard requests through NSPasteboard, opens URLs through NSWorkspace, presents open/save/directory dialogs through NSOpenPanel and NSSavePanel, presents command menus at the current pointer position through NSMenu, reads/writes UTF-8 text files through the shared text-file service contract, and reports the effective light/dark system appearance through the shared HostServiceBridge contract. ApplicationMenu::application items are inserted after About in the standard application menu. The backend installs an Objective-C target/action bridge, keeps the MoonBit command callback alive while installed, and releases the old callback when the menu is replaced. Standard Services, Hide, and Quit items remain AppKit-owned. The native app entrypoint applies that reported appearance to the runtime environment before creating the host driver, so components see the system color scheme on their initial build. AppKit theme-change events use the shared Event::ThemeChanged runtime path when emitted by the local window backend. Right-click context-menu requests use the same NSMenu path and dispatch the selected ActionCommand back through HostRuntimeDriver. File drag/drop events emitted by the local window/macos backend are normalized through Event::DragDrop and dispatched to View::on_file_drop targets. Native WGPU diagnostics can use either the shared Moon Cosmic provider or a platform provider. moui_wgpu_renderer defaults to the CoreText/CoreGraphics provider for runtime measurement and glyph rasterization, explicitly composed with the Moon Cosmic provider as fallback; the Objective-C CoreText stub lives in moui_wgpu_renderer/coretext, while the selectable/composed Cosmic provider lives in moui_wgpu_renderer/cosmic_text. The CoreText provider consumes the shared native FontSpec payload, attempts named families from the structured family stack, maps generic CSS families such as ui-monospace and serif to suitable macOS fonts, registers app-provided font bytes under their requested family alias when CoreText accepts them, and falls back to the system font for unavailable names before the renderer tries the composed Cosmic fallback. Choose the text engine with @wgpu_renderer.native(text_engine=...), then compose it with @macos_host.entry(options=...). Host options can carry a WindowSceneResolver; renderer options stay captured by the provider. core still owns only the neutral FontSpec, TextSystem contract, and deterministic fallback text system; it does not name concrete macOS font files. The canonical examples/showcase/macos_wgpu entrypoint remains a WGPU diagnostic; it selects CoreText with Moon Cosmic as the internal fallback. AppBuilder::run_async_pump uses the optional async launch closure exposed by backend/macos for native app entrypoints that must run moonbitlang/async side work on the same thread as the AppKit event pump. It lets examples/mo_workbench/macos_skia interleave the Skia window pump with its owned Pi JSONL transport worker.

Select the native mainline Skia renderer by importing wzzc-dev/moui_skia_renderer, adding @render_skia.from_env(platform=@render_skia.NativeGpuPlatform::MacOS) to the app builder, and capturing MacosHostAppOptions in @macos.entry. Auto mode offers the direct Metal GPU provider first and the CPU raster provider second. The GPU route attaches its CAMetalLayer to a dedicated transparent host view; if GPU surface creation is unavailable, provider resolution falls back to CPU raster, reads premultiplied pixels after each frame, and presents them through a dedicated NSImageView. macOS Skia options default to the same system FontMgr text path as the Windows and Linux Skia providers; tester-owned first-frame smoke entrypoints explicitly select EmptyTypeface. These paths are intentionally separate from the experimental moui_wgpu_renderer factory; Skia is a renderer package, not a host-core NativeRenderer variant. For local real Skia configuration, direct moon run/moon build commands use the moui_skia prebuild hook and MOUI_SKIA_LINK_MODE=dynamic|static|auto to choose the Skia library mode. Helper smoke runs can pass --link-mode dynamic|static|auto to override the environment for that invocation. The macOS host loop drains RendererEvent image requests, stores only cancellable byte-I/O tasks in backend/common/image, and returns the same opaque token to the selected session. Renderer sessions own format detection, decoding, resource caches, and applied-completion diagnostics; the host keeps no image revision or cache-residency mirror. Applied completions request the matching window's redraw, while stale or disposed tokens are ignored. The real Skia smoke records matching-host async second-frame evidence only when the token completion and repaint markers are present.

Link Flags

macOS host frameworks are injected by moui/build.js for wzzc-dev/moui/backend/macos. Skia/Ganesh libraries and their required frameworks are generated by moui_skia/build.js and used in two distinct places: moui_skia/native/moon.pkg for binding-local tests, and the renderer's final-application link_configs entry.

moui_skia_renderer/build.js reuses the binding's build variables and registers the final-application entry once. The binding package flags do not propagate through a renderer dependency to an is-main application, while registering the renderer entry twice would append every static archive twice.

Example macos_skia entrypoints should not repeat AppKit/Metal/Skia paths. They only need an empty cc-link-flags override so Moon disables tcc -run and uses the system linker for the final binary:

link: {
  "native": {
    "cc-link-flags": "",
  },
},

The host and binding packages declare their own link flags for AppKit, CoreText, WebKit, and Skia symbols. Missing _objc_msgSend, ___CFConstantStringClassReference, CAMetalLayer, or Skia Ganesh symbols usually means the prebuild link_configs did not apply or tcc -run was not disabled.

Use moon run <package> --target native --dry-run -v to inspect the final cc command and confirm AppKit/Metal/Skia flags are present. If moon build works but moon run fails with tcc: error: file 'AppKit' not found, the entrypoint is missing the empty cc-link-flags override.