The extracted headless crate is consumed by BOTH op-host-desktop (the GUI binary, for its embedded --serve-web/MCP/chat/export) AND op-host-web-server — so 'web-daemon' was misleading. Renamed crate dir + package + lib (op_web_daemon -> op_host_services) across all consumer files (114 refs in 24 files) + the 4 Cargo.toml deps + Dockerfile/guard comments; identity docs rewritten (it's the GUI-free host backend — daemon/MCP/AI/export/persistence — not web-specific). No behavior change. (Lock renamed accordingly; the concurrent actor's op-host-web serde line excluded.)
203 lines
10 KiB
TOML
203 lines
10 KiB
TOML
[package]
|
|
name = "op-host-native"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
license.workspace = true
|
|
description = "OpenPencil native host — winit + skia-safe + accesskit backend, integrating jian-skia + jian-host-desktop sub-pieces (spec v19 §3 / §5.2.1)"
|
|
|
|
[lib]
|
|
name = "op_host_native"
|
|
path = "src/lib.rs"
|
|
|
|
[features]
|
|
# `gl-host` (NON-default) enables the desktop winit/glutin interactive runner
|
|
# tier + skia-safe's `gl` feature + accesskit. Consumers that need the GUI host
|
|
# (`op-host-desktop`, `op-app`) opt in via `features = ["gl-host"]`. Left OFF —
|
|
# the default, used by `op-host-services` (via `default-features = false`) and by
|
|
# the mobile `cargo check` (default features) — it yields a raster-only library:
|
|
# no winit / glutin / jian-host-desktop / accesskit, and skia-safe WITHOUT `gl`
|
|
# (so it emits no native GL link directives). The raster `NativeBackend` +
|
|
# `NativeFrameBackend` + offscreen raster + text measurement remain. Mobile is
|
|
# safe by construction: default features = no `gl-host`; the gated deps also live
|
|
# only in the desktop-only target block.
|
|
#
|
|
# Why non-default (Approach Y): cargo can't alias skia-safe twice ("multiple
|
|
# times with different names") and can't make it optional-in-one-target-block +
|
|
# required-in-another; and a `skia-safe/gl` edge in a *default* feature would
|
|
# flip gl on for mobile. Making `gl-host` non-default + opt-in is the only
|
|
# cargo-valid, mobile-safe way to keep skia's `gl` out of the raster build.
|
|
default = []
|
|
gl-host = [
|
|
"skia-safe/gl",
|
|
"dep:glutin",
|
|
"dep:winit",
|
|
"dep:scopeguard",
|
|
"dep:jian-host-desktop",
|
|
"dep:accesskit",
|
|
]
|
|
|
|
# The basic_window demo needs the GL host stack (SharedSkiaContext + winit);
|
|
# `required-features` makes `cargo build --examples` skip it under
|
|
# `--no-default-features` instead of failing on a missing `main`.
|
|
[[example]]
|
|
name = "basic_window"
|
|
required-features = ["gl-host"]
|
|
|
|
[dependencies]
|
|
# Phase 7.3 reorg: openpencil-shell-core dissolved — widget facade /
|
|
# theme / layout scene / scene vars / render-backend / gesture types
|
|
# all resolve through the op-editor-ui crate.
|
|
op-editor-ui = { path = "../op-editor-ui" }
|
|
|
|
# Accessibility (#67): the host assembles every widget's `access_node()`
|
|
# into an `accesskit::TreeUpdate` (see `widget_host/a11y.rs`) for the
|
|
# desktop platform adapter to publish. Pinned to 0.24 to match
|
|
# op-editor-ui + the platform adapter crates' transitive accesskit.
|
|
# Optional + behind `gl-host` (its only user, `widget_host/a11y.rs`, is
|
|
# gl-host-gated) so the raster-only build pulls no accesskit at all.
|
|
accesskit = { version = "0.24", optional = true }
|
|
|
|
# Canvas Preview (Play) mode serializes the document to JSON before
|
|
# building the jian runtime, so the saved doc is never mutated.
|
|
serde_json = { workspace = true }
|
|
|
|
# `WidgetHostNative`'s single source of truth — the canonical-model
|
|
# `op_editor_core::EditorState`. The host derives a read-only paint
|
|
# `Document` from it each frame (see `widget_host.rs`).
|
|
op-editor-core = { path = "../op-editor-core" }
|
|
|
|
# Native-only deps cfg-gated outside wasm32. This is critical (resolves codex round 2 B1 BLOCK):
|
|
# without cfg-gate, cargo would fetch + run skia-safe's build.rs (which fails on wasm32),
|
|
# and the Step 5 grep `must NOT be compiled for wasm32` would never match — masked by
|
|
# the skia build error.
|
|
#
|
|
# v19 pivot (Task 1): add P0-pinned GL stack + jian-skia + jian-host-desktop.
|
|
# - P0 dep-stack pin comes from the P0 probe (plan v7 §Task P0; skia-safe 0.97 + glow 0.17 +
|
|
# glutin 0.32.3 + glutin-winit 0.5.0 + winit 0.30.13 + raw-window-handle 0.6.2 +
|
|
# scopeguard 1.2 all GO on macOS/Windows/Linux).
|
|
# - jian-skia (textlayout feature) provides SkiaBackend impl + skia textlayout (replaces parley).
|
|
# - jian-host-desktop (target-gated desktop only, without the `run` feature) reuses
|
|
# PointerTranslator / scene::collect_draws_with_state / DesktopHost config helpers;
|
|
# OP runs its own GPU event loop and does not call jian_host_desktop::run (softbuffer
|
|
# raster present is not needed).
|
|
#
|
|
# Desktop GL stack — target-gated to macOS / Linux / Windows. iOS / Android
|
|
# pull EaglProvider / AndroidEglProvider stubs (Step 1f) which don't need
|
|
# glutin / winit / desktop skia-safe gl bindings; spec §11 invariant 1 says
|
|
# shell-native must compile on mobile cargo check (verified by CI mobile-check
|
|
# job in rust-multiplatform.yml). winit features note: on Linux you MUST
|
|
# explicitly enable `x11` and/or `wayland`, otherwise `platform_impl/mod.rs`
|
|
# triggers `compile_error!`. macOS / Windows backends are auto-enabled via
|
|
# cfg(target_os) and need no feature flag.
|
|
# Cross-platform abstraction deps — pulled for ALL non-wasm targets including
|
|
# iOS / Android. The `GlContextProvider` trait (spec §3.1) references
|
|
# `glow::Context` in its method signatures and Step 1f Eagl / AndroidEgl
|
|
# stubs reference `raw_window_handle` for `on_resume`; both must be importable
|
|
# on mobile per spec §11 invariant 2. `glow` and `raw-window-handle` are
|
|
# pure-Rust thin bindings — no native build steps on iOS / Android.
|
|
# `jian-core` is wasm32-clean per P0.5 and platform-neutral on mobile.
|
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
|
jian-core = { path = "../../vendor/jian/crates/jian-core", version = "0.0.1" }
|
|
glow = "0.17.0"
|
|
raw-window-handle = "0.6.2"
|
|
|
|
# The canonical loader / `EditorState` → paint-`Document` bridge.
|
|
# Desktop-side (depends on skia via jian-skia's SkiaMeasure), so it
|
|
# is gated outside wasm32 alongside the rest of the native stack.
|
|
op-pen-loader = { path = "../op-pen-loader" }
|
|
|
|
# The canonical `.op` schema — `WidgetHostNative` names
|
|
# `VariableScalar` when committing variable-row edits onto
|
|
# `EditorState`. Already a transitive dep via op-editor-core.
|
|
jian-ops-schema = { path = "../../vendor/jian/crates/jian-ops-schema" }
|
|
|
|
# Cross-platform widget render stack (desktop + mobile, NOT wasm).
|
|
#
|
|
# 2026-05-10 mobile extension (per user note that jian will eventually
|
|
# need iOS and Android): skia-safe + jian-skia move out of the desktop-only
|
|
# block so `NativeBackend` + `widget_host` compile on iOS / Android
|
|
# too. skia-safe's `gl` feature is desktop-only (iOS deprecated GL —
|
|
# Metal goes in Step 1f; Android uses GL/Vulkan via the platform
|
|
# provider, not via skia-safe's bundled GL bindings here).
|
|
# Mobile cargo check pulls skia-safe with no GL feature, exercising
|
|
# only the raster + textlayout paths that the inspector slice needs.
|
|
# Spec §12.3 jian boundary invariants 2 & 3 — REVISED 2026-05-10:
|
|
# Invariant 2 now allows `jian-skia` on mobile (the widget render
|
|
# stack uses it); `jian-host-desktop` remains forbidden on mobile
|
|
# because it carries winit / glutin / desktop-only host glue.
|
|
# Invariant 3 (wasm32 forbids both) is unchanged. The
|
|
# `tools/check-jian-boundaries.sh` script enforces the revised set
|
|
# alongside the script header rationale.
|
|
[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows", target_os = "ios", target_os = "android"))'.dependencies]
|
|
skia-safe = { version = "0.97.0", default-features = false, features = [
|
|
"binary-cache",
|
|
"textlayout",
|
|
] }
|
|
jian-skia = { path = "../../vendor/jian/crates/jian-skia", version = "0.0.1", features = [
|
|
"textlayout",
|
|
] }
|
|
|
|
# Desktop-only GL stack — `gl` feature on skia-safe, plus glutin /
|
|
# glutin-winit / winit / jian-host-desktop (all GUI-host glue that
|
|
# does not apply to iOS / Android, where the host is a UIKit /
|
|
# Activity wrapper — Step 1f scope). Cargo deduplicates: skia-safe
|
|
# resolves to one crate version with the union of features (binary-
|
|
# cache + textlayout from above + gl from here on desktop only).
|
|
# winit features note: on Linux you MUST explicitly enable `x11`
|
|
# and/or `wayland`, otherwise `platform_impl/mod.rs` triggers
|
|
# `compile_error!`. macOS / Windows backends auto-enable via
|
|
# cfg(target_os) and need no feature flag.
|
|
[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dependencies]
|
|
# skia-safe's `gl` feature is added via the `gl-host` feature (`skia-safe/gl`),
|
|
# NOT here — so with `gl-host` off the raster/mobile build links the 5-OS
|
|
# skia-safe above WITHOUT `gl` and emits no native GL link directives. The 5-OS
|
|
# entry is the single skia-safe edge; no desktop-only skia-safe entry is needed.
|
|
glutin = { version = "0.32.3", optional = true }
|
|
# `casement` — ZSeven-W's winit fork (vendored as a submodule under
|
|
# `vendor/casement` so CI checks out the same source the desktop binary
|
|
# links). The `package` key keeps the `winit` import name. `glutin-winit`
|
|
# is intentionally NOT used: it hard-depends on the upstream `winit`
|
|
# package, which would pull a second, incompatible winit into the
|
|
# tree. Its only use here — `GlWindow::build_surface_attributes` — is
|
|
# replaced by a direct `glutin::surface::SurfaceAttributesBuilder`
|
|
# call in `context/provider.rs`.
|
|
winit = { package = "casement", path = "../../vendor/casement", default-features = false, optional = true, features = [
|
|
"x11",
|
|
"wayland",
|
|
"wayland-csd-adwaita",
|
|
"rwh_06",
|
|
] }
|
|
scopeguard = { version = "1.2", optional = true }
|
|
jian-host-desktop = { path = "../../vendor/jian/crates/jian-host-desktop", version = "0.0.1", default-features = false, optional = true, features = [
|
|
"textlayout",
|
|
] }
|
|
|
|
# tracing for span instrumentation across SharedSkiaContext / NativeBackend
|
|
# (spec §3.3 / §5.2.1; Task 2 Step 15 dictates per-method spans).
|
|
[dependencies.tracing]
|
|
workspace = true
|
|
|
|
# thiserror for ProviderError / SharedSkiaError enums (context module).
|
|
[dependencies.thiserror]
|
|
workspace = true
|
|
|
|
# Task 2 dev-dependencies (spec §9 + plan v7 Steps 16a-16f):
|
|
# - sysinfo: 100-loop RSS sanity (memory_loop.rs)
|
|
# - tracing-test: capture span emission (tracing_spans.rs)
|
|
# - khronos-egl: Linux EGL pbuffer GPU smoke (gpu_smoke.rs / gpu_chrome_stub_composition.rs)
|
|
[dev-dependencies]
|
|
sysinfo = "0.30"
|
|
# `no-env-filter` is required for integration tests — the default filter
|
|
# only captures logs from the test crate itself, but our `#[tracing::instrument]`
|
|
# spans live inside `op_host_native::*`. (Per upstream README §136.)
|
|
tracing-test = { version = "0.2", features = ["no-env-filter"] }
|
|
|
|
# EGL pbuffer dev-dep is Linux-only — macOS/Windows GPU smoke takes other
|
|
# paths (invisible winit window / manual). Gating with `target.'cfg(...)'`
|
|
# keeps `cargo check` on non-Linux quiet about the un-fetchable pkg-config
|
|
# requirement. khronos-egl 6.x covers Mesa softpipe pbuffer creation.
|
|
[target.'cfg(target_os = "linux")'.dev-dependencies]
|
|
khronos-egl = { version = "6", features = ["dynamic"] }
|
|
libloading = "0.8"
|