The Makepad Builder (tools/makepad_builder: the Windows download is makepad-builder.zip with the Builder's source; macOS and Linux run makepad.sh), the CI runner (tools/ci), cargo-makepad, the agents tool, the root workspace and the documents.
Covers work 6f1e44649..2b1a41df4 outside platform, draw, widgets, libs, apps and examples:
- wm: the Android super-app compiles tiles on the phone against the host engine
- cargo-makepad: the super-app APK is packed by `android dyn-pack`, in Rust
- widgets, storybook: the widget catalogue app, some eighty new widgets, a theme store with mixable style sheets, and the rule that a press belongs to
- wm, widgets: the style tween starts with all eight weights, and the new style sheet takes the last number instead of macOS's
- platform: the Android desk swipes at 120 Hz — offscreen render passes and framebuffers cached, SVG meshes kept, font families that complete
- cef: a page's audio can be captured instead of played
- Button: activate from the keyboard when focused (#1241)
- libs/ai: exclude hub_ui and services from the AI workspace (#1242)
- flow: the flow-ui app and the flowgraph canvas return to the workspace, with staged progress in libs/flow
- svg: a stroke that bends tighter than its half width collapses its inner edge to the corner
- the accent a name is written with stops deciding whether search finds it
- macOS: keep the paint clock beating while the window is minimized (#1244)
- Linux: only link libdrm for the direct backend (#1245)
- cargo-makepad: find dependency crate dirs via cargo metadata (#1246)
- app_main!: only ship the fonts an app declares (#1247)
- ai stems: LaneDemixer, VocalsModel and the platform Stage origin/main needs
- platform, widgets, wm: every Vulkan pass renders through a negative-height viewport again, so a Wayland or X11 window stands upright, and no capture
- calendar: its own colour contrast is named explicitly, now that the theme store exports one under the same name through the widgets glob
- widgets: the supersampled resolve and the map's shadow mask sample their textures as stored, like every other render texture
- platform: every OpenGL texture pass stores top-left rows, custom cameras included, and culls with the winding its inverted projection gives
- platform, wm, director: a hosted app's software frame arrives as a top-left texture and the window manager and the director carry no flip term at al
- widgets, platform: the last twelve warnings go
- The Builder compiles itself again from the Makepad tree Scope's release pins and removes the source snapshots nothing is built from any more
- The regex engine accepts \b and \B, reports the earliest match so a scan can resume after it, and can decide word boundaries on ASCII so a code sear
- workspace: Scope's settings carry the code map's tab width and the directories each prepared project hides from its map
- AGENTS.md: a platform change made for one application needs the user's feedback and checks first, and app specifics never leak into the shared layer
- wm: the desktop style menu lists each style once
- cef, video, platform: what Stage's browser needs from the shared layers
- macOS: re-arm the display links when a window leaves the Dock (#1251)
- platform, wm: work builds again on iOS, tvOS and wasm, and the window manager is warning-free on Windows
- ci: tools/ci, a Splash runtime that watches a branch and runs every ci.splash it finds
- stitch: the crate says what the rest of the repository says about its license
- ci: a run is one target dir and one cargo batch per target, and the wall draws
- ci: the wall shows THIS run and is fit for an OLED
- ci: untested is grey and nothing else
- ci: warming fills the cache and blames nobody
- Vulkan: stop printing the loader's startup narration by default (#1252)
- ci: the terminal gets its pty helper, director is a desktop tool, and a refused input is asked again
- platform: no warnings on tvOS and linux_direct, and a missing pty helper says so
- apps: what the CI box found
- ScrollBar: add `show_handle` for a view that scrolls without a grabbable bar (#1254)
- cargo-makepad: keep the android SDK at a stable path (#1253)
- ci: the window is a dashboard
- Remove Flow, asset and VJ applications moved into Stage
- ci: a stop or a restart is not a test result
- ci: a quiet header, a build that visibly moves, and scripts that leave the machine alone
- widgets: children a lookup discovers reach the dump, the snapshot and the flood searches
- tests: the workspace suite, run as a whole for the first time, passes outside the example UI tests
- platform: a hidden window wears no hands-off frame
- examples: the UI tests pass, for the reasons they failed
- ci: a library's warnings turn the workspace block yellow, and a desktop tool is not warmed for the web
- libs: no warnings in the workspace check on any row
- ci: the workspace script gives the wall back after warming
- ci: a judgement is never lost to the way it was phrased, and every "retry" of the bridge is retried
- tests: the last three failures of the CI box's night
- Linux: fix window chrome button hovers and how maximized/fullscreen windows work (#1255)
- ci: the header names the tip being tested
- tools: makepad-screen is makepad-agents, and its binary is `agents`
- gif: the crate's doc examples compile
- ci: the tests are the platform's own, in release, in two minutes
- Tooltip: position anchored tooltips in the same draw (#1256)
- cef: a hosted browser survives its host's exit
- ci: a card is as high as its content
- tests: the three binaries over ten seconds in release come under it
- widgets: let the host install script mods into every Splash isolate
- widgets: a pooled test context forgets the last case's Escape claim
- widgets: the pooled test context's resets replace the globals
- wm: the shell menu says what it did, and the CI waits for that
- platform: the storage module says how much a volume has free
- git: the memory ledger can take what it is asked for
- ci: a driven app takes every key once, and the storage module builds for the browser
- RadioButton: fix its touch hover state and click-off behavior (#1258)
- HtmlLink: fix its hover and pressed states (#1257)
- RadioButton: take key focus on the click, not on the press (#1259)
- script: re-entrant dispatch, thread index validation, Any-based handle downcasts, UTF-8 previews; regex: never_loop fix
- script: port Octoscript WS1 — worklist equality with fuel/deadline/work bail, uncaught-error bail, allow_debug_output
- script: port Octoscript parser/tokenizer/control-flow VM patches (ws2)
- script: port Octoscript heap/string/array/object hardening onto upstream's allocation budget
- script: port orphaned Octoscript VM hardening (execution caps, clear_type_methods, parser diagnostics)
- script: keep silenced streaming evals running past uncaught errors
- script: the Octoscript hardening keeps a Makepad host's semantics and its speed
- fix(text): enable ttf-parser gvar-alloc for many-tuple variable fonts
- feat(text): CoreText outline fallback for hvgl-only fonts (macOS)
- draw text: the CoreText outline fallback is only ever resolved for a face whose outlines live solely in hvgl, and font-family diagnostics are the `f
- mail: the phone layout lines up
- clock: the phone layout fits both orientations
- calendar, reminders, calculator, sheets: the phone layouts fit their space
- platform, widgets, wm: a touch that is taken away is cancelled, never released
- weather, notes, finance, photos, route: the phone layouts tidy up
- files: the phone layout tidies up
- wm: the phone shell's surfaces match the app and the grid
- wm on Android: every app is its own process
- clock: a cancelled release neither opens an alarm nor switches tab
- platform, wm: hosted apps ask the WM for what they cannot do themselves
- wm on Android: apps build on the phone
- wm on Android: app transitions and gestures feel like the phone's
- android: rotated Vulkan windows stop rebuilding their swapchain every frame, and hosted children get touch
- vulkan (android): a window released on suspend is not released again
- android: hosted children hand frames over with GPU fences and draw only when they have work
- wm on Android: gestures and surfaces settle like the phone's
- widgets: touch lists scroll with Android's physics
- wm on Android: the shell follows the Pixel launcher's motion
- wm on Android: Recents shows the apps over a receding home, and the home screen switches looks
- wm on Android: the look switcher stays put, the iOS dock shows its icons, background apps follow a look change
- task, cargo-makepad, widgets, audio: the task manager chooses its columns, graphs every process' network and disk traffic and installs itself as a D
- agents: a user touching an app under test no longer stops the agent
- flowgraph: ordered ports take many wires, sockets can override their icon, and the canvas embeds as a viewport
- cef: captured frames and audio carry callback clocks and a navigation epoch
- git: timings read a portable clock
- ai: the hub's rig-fixture tests find the asset library without the asset client
- ai llm: a Metal main buffer is filled in 32 MB chunks
- diskmap: a scan lists each macOS directory in one getattrlistbulk call and classifies files without allocating or locking
- files: the tile view's three projections are toolbar buttons
- mail: the local view takes a theme-derived palette and line icons, search pages share records
- director: agent lanes form a tree and Grok joins the usage bar
- widgets, draw: skeuomorphic surfaces light each other through an optional relief buffer
- widgets, platform: a texture can light the relief buffer, menus take colour chips, and a style reload recompiles changed shader functions
- widgets: relief surfaces can travel like mechanical keys, and dark surfaces take less neighbour light
- platform, widgets, audio_route, ai: window crossfades and whole-frame presents, caption controls that click, themed menus, a stereo-pair audio tap,
- builder: the Builder TUI matches the new terminal design, Windows executables carry app icons, and every app has one
- platform: Android builds without Vulkan compile again, and the font-selection test counts the hosted entry point
- platform: the pipeline-skip repaint mark exists only on Apple, where Metal reads it
- builder: the terminal scripts delete nothing and read top to bottom, and every Builder delete stays inside its own folder
- files: the Files app deletes nothing and never overwrites
- director: coding agents ask before acting unless you choose otherwise
- sheets, score, git, home: saves cannot cut a file short or overwrite another one, and checkouts cannot write outside the repository
- git: worktree status matches git on real repositories and can be cancelled
- builder: one forward-only bar per setup component, green checks on finished setup rows, a black Builder window and a smaller Windows ZIP
- builder: the GPU notice is remembered
- cuda: builds link only the CUDA toolkit they are given, never a system install
- builder: a refused email opens the editor again with what was typed and says why, and the app section is YOUR APPS
- builder: a refused email says "Email not recognised" and keeps what was typed for fixing
- platform (windows): every window keeps animating with several windows open
- builder previews: long work gets a page of its own (steps as a checklist, the current one carrying its bar, footer working · ctrl+c stops), Account
- builder: long work runs on its own page
- builder: a first build resolves online, the Rust row and bars move when the work does, and the window fits the TUI
- audio_route: one API on macOS, Windows and Linux, monitoring by default and processing only when asked, plus shaders that discard a value compile to
- platform, widgets, ai: a restyle recompiles nothing it already has, shows only complete frames, and a window can own its caption
- builder: Compile shows a real bar
- builder: the compile line is the bar and n / total crates
- builder: apps get the icon their package declares
- builder: no Scope command
- widgets: relief surfaces can swing their light toward a point
- builder: a HEAD request is a HEAD
- builder: the menu waits for a choice
- builder: no menu flash after log-in
- builder: wait out Windows security on fresh Rust
- builder: the menu opens on the first of YOUR APPS
- platform (windows): half-float RGBA textures have four channels
- builder: CUDA whenever the machine has NVIDIA
- audio_route example: print the samples that reached the processor each second
- widgets, builder: the big widget families are features, all on by default, and the Builder takes none of them
- platform (macos): the display link is kept until it is invalidated
- ai hub: a local chat with no model says so once, plainly
- builder: the Windows exe is built for size
- windows: desktop apps open no console window, and still speak through pipes
- ai: Claude Desktop drives any app with the F10 panel
- Constrain Splash external I/O to the host service bridge (#1243)
- PortalList: stop following the end when scrolling to an earlier item (#1261)
- wm: starts on Windows
- ci: a full disk empties the build output before the run, not every row after it
- builder: an incremental compile's bar follows what really compiles
- builder: the compile bar's total is the app's own crates
- builder: menus wrap around
- wm: children open no console windows on Windows
- wm: the whole deck out of a Builder's source, compiled only when the person opens an app
- builder: CUDA crates build in an installation whose path has a space
- ai: Connect hands the .mcpb to Claude Desktop itself
- wm: the clock and calendar know the date on Windows
- platform (windows): a popup opened for the first time draws its rows
- wm: opening an app rebuilds it when its binary is out of date; warm instances never build
- builder: an app edited after its build shows as needing a compile
- civil-time: one local wall clock for every app, and it knows the zone on Windows
- platform + wm: a hosted child redraws at its tile's new size
- platform (windows): a texture pass drawn before its window has a size is skipped, not a crash
- draw: glass of a view that stopped drawing leaves the screen
- calendar: the Calendars sheet is an opaque panel, and the wide layout does not float one over its sidebar
- build: dev keeps line tables only, release is incremental without LTO, the parallel frontend is a documented local opt-in
- cargo-makepad: a binary with several app_main! entry points bundles
- script: #[derive(Script)] emits one helper call per field, and ScriptNew's default methods keep their bodies out of every type
- widgets: the Widget lookup methods and with_script_vm_id are compiled once, not once per widget type
- platform: studio-protocol no longer waits for script, so platform starts ~0.5 s earlier
- ai-speech: makepad-ai-sfx (and with it ai-h3) is built only for IndexTTS
- platform: an app's package dir, icons and bundle name rebuild only that app
- script + wasm_bridge: no build script that reruns on every file
- build: a private app cloned into apps/<name> joins this workspace, Stage first
- build: the AI stack, csg, Scope and Source Library join the one workspace
- builder: every app builds in the one Makepad workspace, one target directory per source snapshot
- ai chat: the chat's backends are the CLI, MCP and cloud providers; the local model is the `localai` feature
- apps: every app that hosts the chat has a `localai` feature for the local model, off unless the app's own job runs one
- builder: time each install component and phase
- builder: Build tools, Windows SDK, Rust and CUDA install side by side, each with its own bar
- builder bootstrap: rustc, rust-std and cargo download and unpack side by side under one Rust bar
- widgets: the library moves to makepad-widgets-core in widgets/core, and makepad-widgets becomes its front crate
- widgets: the Window, widget tree and panel theme reach the tweaker, voice, AI slot and dock through hooks, not through their modules
- widgets: every widget family is a crate of its own under widgets/families, and makepad-widgets links, re-exports and registers the ones its features
- aichat, widgets: the chat reads the design feedback through the tweaker's hook, so linking the chat no longer needs the tweaker
- apps, examples, libs: each crate builds only the widget families it uses, and the design overlay is each app's own default feature
- builder: an app release builds without the app's development defaults, and the catalog names every feature a release ships with
- widgets: the build scripts rerun on their own edits only, and makepad-widgets no longer reads MAKEPAD
- livepipe: takes makepad-widgets without its default families, now that the AI stack is in the one workspace
- builder: the catalog names the new localai defaults of route and ai-hub
- feedback: Send feedback, a caption icon and a small panel that shows exactly what is sent
- builder: an app it launches knows who the person is, for Send feedback
- feedback: the panel's wording reads right and draws in any font
- feedback: takes makepad-widgets without its default families
- builder: clear build data deletes target/ itself and says why when it cannot
- ai chat: a build without local AI starts on the first provider that answers here, not on "No model"
- platform: MAKEPAD=gpusim builds again
- cargo-makepad: a Windows desktop build links the app's icon into its own binary, not into RUSTFLAGS
- thiserror: RUSTC_BOOTSTRAP no longer turns on the unstable generic member access API
- builder: every end-user build uses rustc's parallel frontend, and falls back to one thread when it fails
- builder: the Windows SDK downloads the 25 cabinets its MSIs name instead of all 149, no screen or log shows a \\?\ path, long status messages wrap,
- builder: CUDA kernels compile in any install folder, and when they cannot the app is built without them
- builder: makepad-builder.exe declares itself like a well-formed Windows program and stops a stalled build through a job object instead of taskkill
- platform (macos): a contained panic no longer frees the windows under AppKit or leaves an app that ignores quit
- builder: macOS and Linux run the Builder as one shell script, the same TUI as Windows, and nothing is compiled for it
- builder + ai-cuda: the CUDA kernel progress shows in the Builder's Compile row, not scribbled over its screen
- builder: an app built with CUDA starts on Windows
- builder (windows): the downloaded exe is built large again
- builder (unix): the email check takes real addresses
- repo: no third-party comic archive, generated models or sample asset in the tree
- remove big example media files
- cargo_makepad: no stray KNMI radar frame in the Android Java sources
- widgets: the empty parts of an app's caption bar drag the window again
- ScrollBar: fade out when idle, like macOS overlay scrollers (#1264)
- platform: every app builds the same `windows` crate
- wm: in a Makepad Builder installation apps build through the Builder, however wm was started
- platform, draw: web builds start again
- platform: web text draws again
- widgets: the keyboard reaches boxes and modals
- widgets: a hover tooltip never sits under the mouse cursor
- platform: clipboard_read, reading text or an image from the system clipboard
- feedback: Send clipboard, and the dialog works from the keyboard
- builder: the Windows Builder ships as source, runs in its own console, and apps compile with Rust's GNU toolchain or Microsoft's
- platform: an app also finds its resource map in the builder folder beside it
- win_resource: PNG decode and encode on makepad-fast-inflate instead of zune-png
- builder: one folder layout everywhere, makepad-builder.zip with only the files a Windows build reads, a Rust download over parallel connections, and
- builder (windows): the .bat runs from a folder with spaces and parentheses, and the ZIP always carries it with CRLF
- builder: coding agents start from the macOS/Linux Builder, its compile bar has its end, the app rows say where each app is in a word or two, and Win
- builder (unix): running curl | sh again opens the existing installation with its saved email
- builder: log out from the Account row
- builder: `makepad-builder build APP` compiles an app offline exactly as the Builder does
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- task: a right-click column chooser (sections as flyouts, Default Columns), every figure and graph its own sortable column, dragged order and widths saved; per-process network bytes/packets from the kernel's ntstat control socket (matches nettop, no root), disk bytes, footprint and idle wake-ups every tick; history journal v4
- widgets: data_grid_columns, one column helper (chooser, reorder, resize, fit, sort cycle, layout text) that task uses and other tables can reuse; the menu engine refreshes marks inside an open flyout; the segmented control centres its labels on the line height and no longer glides after a moved row
- svg: a stroke join never connects to the previous subpath (the diagonal through outline icons)
- platform: home::app_data_dir; script: ScriptIp body ids widened to 14 bits (16384 bodies, was 4096) with an index of 26 bits, and a clear stop instead of aliasing past the limit
- audio_route (new): tap an app's audio output through the Core Audio process tap into a host processor (equalizer, gain, limiter, analyzer) and play it; audio_picture owns the one FFT; audio_decode probes tags and length from a file's head and tail; search::fold_words; zip_file reads archives with a trailing comment
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The SDK came from `env!("CARGO_MANIFEST_DIR")`, so every copy of the binary had
its own NDK at its own path. Switching copies changes `CMAKE_C_COMPILER`, and
cmake then deletes its cache and re-configures *without* the `-D` flags, losing
`CMAKE_SYSTEM_NAME=Android`. Deps like `aws-lc-sys` then build for the host and
Darwin forces `-arch arm64` into the NDK clang.
* default to `~/.makepad/<host-dir>`, independent of which binary runs
* migrate an existing per-checkout SDK with a single `rename`
`cargo tree` only prints a directory for path dependencies, so for a git
dependency we fell back to the `<crate>.path` file its build script drops
in the target dir. Any tool that prunes the target dir deletes that file,
and a warm cache means the build script never re-runs to recreate it, so
`add_resources` silently found no `resources` dir for `makepad-widgets`
and packaging failed with "font assets declared by makepad.font-assets.v1
are missing on disk". Ask cargo for each package's `manifest_path`
instead, keeping the `.path` file as a last resort.
Measured on the Pixel 11 Pro XL (PowerVR): a pane swipe presented at
~84 fps on the 120 Hz panel, a vsync dropped every three to six frames.
simpleperf showed 22% of the CPU in the driver's shader compiler and 24%
in its render-target teardown: the Vulkan backend created a VkRenderPass
and a VkFramebuffer for every offscreen pass on every frame and destroyed
them after the fence, and on this driver each render pass compiles a
load-op shader. Offscreen draw render passes now live for the device
(keyed by formats and load/store ops) and framebuffers are cached per
render pass, attachment views and storage extent, invalidated through
texture retirement so they die after the frame that used them.
The app icons were re-tessellated from SVG every frame: one DrawSvg kept
one scale and the desk draws each icon at two or three sizes. A DrawSvg
keeps up to four meshes per device scale; the geometry pool defers frees
and releases them once per frame against the geometry ids the live draw
lists still name, so a retained draw call never sees its slot reused.
A font member whose resource can never load (the WM referenced Inter and
its other faces through `self:../../widgets/...`, unmapped in a package)
kept its family incomplete, and an incomplete family is redefined every
frame: the layout cache cleared, every label laid out again, the asset
reopened. Such a member drops out of its family once, logged, keyed on
the resource registry's generation so a resource that appears later is
asked for again. The WM names its fonts through `makepad_widgets:` and
reads the clock in-process on the UI thread instead of forking `date`
twice a second.
Android gains a `frame.cpu` trace (events, next-frame, draw and repaint
milliseconds per drawn frame) and a profileable manifest so simpleperf
can sample a release build. The dyn-pack tile proof tolerates the app's
own Dirty line after an engine rebuild.
After: SurfaceFlinger presents every swipe frame at 8.3 ms, the render
thread runs at ~45% instead of 85–97%, and the frame is paced by the GPU.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`cargo makepad android dyn-pack` stages the relocatable checkout,
cross-builds host + engine from it through the ordinary Android build,
proves every tile's on-device command against that target/, packs the
APK with the phone toolchain, the checkout and target/ as streamed LZ4
tar parts, and rehearses the phone's first tile open from the packed
APK; `dyn-rehearse` runs that last gate alone. This replaces the
Python and shell pipeline that lived outside the tree. The stage
directory is tool-owned, every cargo phase runs under one controlled
environment recorded in the target's marker, rustc runs through
cargo-makepad itself as the remapping wrapper, and the APK is renamed
into place only after signing and the rehearsal. The host package
names its engine and tiles in [package.metadata.makepad.dyn]. Only the
three /system/bin/sh templates that run on the phone stay shell.
libs/rmeta is the rustc metadata header reader apps/wm used, now shared
with cargo-makepad; libs/tar gains a streaming ustar writer with GNU
long names; the zip writer streams to any sink so a 900 MB APK never
sits in memory.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
tools/makepad_builder replaces tools/makepad_loader: one build target
shared across app builds, workspace package selection, checkout
progress on the public Git API, detached built apps with a completion
state, waits for Windows security scans, manual retry after compiler
locks, dedicated-folder installer checks, catalog and runtime fixes.
tools/web_server and its scripts leave for github.com/makepad/webserver.
Arch USB clone/restore scripts, the qwen38 box scripts and the G-belt
serial test join tools/. docs/agents records the agent workflow and the
remote-control handoff protocol; AGENTS.md forbids vendored sources and
bulk imports. Cargo.toml lists apps/wm-dyn, libs/code_language,
libs/search, libs/tar, libs/loader_bundle and tools/makepad_builder,
and drops the two removed crates.
Squashed from work:
- Share Builder target across Makepad app builds
- Fix Builder workspace package selection
- Align Builder checkout progress with public Git API
- Detach built apps and show completion state
- Wait for Windows security scans
- Offer manual retry after Windows compiler locks
- docs: the agent workflow of record and the remote-control handoff protocol
- builder: dedicated-folder installer checks, catalog and runtime fixes; Windows job objects hold c_void handles
- tools: Arch USB clone/restore scripts, the qwen38 box scripts, and the G-belt serial test
- tools: the web server moves to makepad/webserver
- AGENTS.md: no vendored sources or bulk imports in the tree
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Squash of 55 work commits (Sep 1–12):
0fd356d windows: the vendored bindings are generated from a checked-in filter
79882b5 fabric: a photo or a live camera to a fitted sewing pattern
1e93309 AGENTS.md: designs stay local; no OS screenshots; focus and hidden-window laws
aa96dbd cargo-makepad wasm: package the bin target's wasm and create dirs before minifying
14d0723 cargo-makepad wasm: production packaging — strip, small profile LTO, optional binaryen, size report
79e7526 sqlite: a page-store seam — the file backend as before, an in-memory backend, and open_memory / open_with
60ee978 cargo-makepad: package artifacts carry a content hash so a re-upload is a new URL
611c9eb cargo-makepad: production packaging stays off fat LTO; script VM under LTO investigated
ab8febc cargo-makepad: fonts packaged from the app's font manifest
f6bbee9 wasm bridge: shared memory asks for the 4 GiB wasm32 ceiling and steps down where the engine refuses
fb1416d cargo-makepad: the threaded wasm module is linked with the 4 GiB wasm32 memory ceiling
fd5d70c cargo-makepad: the app's own resources are packaged under its bin name, which is how self:// resolves
f51ca07 workspace: the wasm interpreter's tests build at opt-level 1 — its own profile setting is ignored inside a workspace, and opt-level 0 overflowed the script eval stack
942ff86 sqlite: the browser store has one owner — its locks never wait on a clock
82d0cfa web path: the trace helper keeps its doc, the journal nonce steps a counter where there is no clock or pid
6f8c08f web-server: POST /api/crash stores crash reports in a rotating log on both servers
106b38c wasm bridge: the imported memory honours the module's declared limits
94b8726 dj-pack: tracks in, stems through the hub, a site store snapshot out
d9f04fc dj-pack: pack reads caches, never creates them; dry-run writes nothing
e6a305c ai-hub + dj-pack: a whole track fits a stems job; long tracks split into spans
d1910b8 web-server: a store snapshot's extensionless routes are served with the types the exporter recorded
c1f7b53 asset-client + dj-pack: a long description never rejects a snapshot; the packer writes one bounded line
453197d dj-pack: analyse produces the beat grid, overview and loop-splat caches the demo cache ships
9b4a3ca network: every completion raises the UI signal
fad1c49 web server: audio and text files are served, and models/ is immutable like maps/
569b4a7 dj-pack: every CC BY and CC BY-SA version and the public domain mark are redistributable licences
dc9cce6 workspace: no std clock on the web in any crate the web apps link — the last start-up worker death is gone
c7639f0 clippy: timed std waits (sleep, recv_timeout, wait_timeout, park_timeout) are disallowed — they read the std clock and panic on wasm workers
d748753 wasm bridge: the page environment carries js_worker_wait so the module links — the pool landing added the import for workers only
ec40fdb vj + widgets: double-click a knob or fader to reset it to its default — the Slider handles tap_count 2 and emits its normal Slide action; the deck controls carry their neutral defaults (pitch 0, gain/EQ/stems 1, filter centre, crossfader centre)
fe23e06 AGENTS.md: the execution policy — zero locking on the UI thread as one mechanism for native and wasm, no temporary threads (the pool), the standard operating flow (Codex codes, Fable designs and reviews, Grok tests), and the tweaker on Shift+F10
e689aea web_server + geodata + route: live radar, wind and weather on makepad.nl/api — one bounded poller per feed, hourly, disk-backed cache served from an Arc snapshot (a restart never re-polls early), 503 warming until the first result, health reports ok/warming/unavailable with timestamps; KNMI key from --knmi-key-file, the documented anonymous open-data key otherwise; libs/geodata fetches through the platform HTTP client instead of shelling out to curl; the client retries 503 after 30 s and disables a layer only on 404
cd33943 web_server: radar and weather run on KNMI's documented anonymous key when no --knmi-key-file is given; without --live-cache the pollers keep an in-memory cache and say so once
2f3e393 web_server: a directory path without its trailing slash (/score) redirects to /score/ instead of 404, query preserved
9a31d21 flow-ui + widgets: a chosen model shows no node list, and a closed ComboBox shows the start of a long label
22b2c78 docs: streamline agent runbook and extract reference guides
6058284 terminal: add hostable session multiplexing via tools/screen
8a9345b tools: migrate Cargo.toml lookups to segment-path keys
8749b91 counter: keep app state across Splash reloads
3ffd485 tools: add agent launcher and AIHub node update and smoke scripts
c33a9d3 screen: add bypass and resume menu options
c40d234 AGENTS.md: current delegation hierarchy (Grok mechanical, Codex hard, Fable manages)
4184455 Workspace: scope lives at apps/scope (clone of makepad/scope)
27844c9 makepad arch usb builder
dd967eb Workspace: drop nine members that are not in the repository
1961768 AGENTS.md: hierarchy 2026-09-11 — Fable builds, Codex reviews, Grok proves
9cd9f94 AGENTS.md: rendering is verified on the real GPU backend, headless is for logic tests only
5f53254 AGENTS.md: GPU proofs may run hidden; only the headless CPU backend is out
e950b08 docs: app-remote — hidden GPU runs vs the simulated-GPU backend, measured grab cadence, remote hazards
9c94a77 arch: the platform plan names the simulated-GPU backend gpusim
3009257 micro_serde: serde_json-style JsonValue accessors, pretty printer, depth limit and strict parse
134cd76 gitignore: alternate target directories, root scratch dirs and stray logs are never source
60ba86e arch: the render node refs name platform/src/os/gpusim/mod.rs
1dc571a tools/arch_usb: Wi-Fi, Intel GPU firmware, the AI hub service and game-hardware udev rules on the Arch image; the WM session script picks the saved compositor GPU
cc3b05a tools/arch_usb: a polkit rule lets the arch account start, stop and restart the WM service
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Event: trace cancel scopes, and gate StackNavigationView's Back on ownership
A scope held by a widget that has stopped being the active thing wedges
Escape and the back gesture for everything behind it, and the only symptom
is that the gesture silently stops working -- which is indistinguishable
from there being nothing to cancel. MAKEPAD_CANCEL_TRACE=1 now logs every
scope begun and ended, and which one each press was stamped to, each named
by the call site that began it.
That location comes from #[track_caller] on both Cx::begin_cancel_scope and
CxCancelScopes::begin: the attribute propagates through the chain, so
Location::caller() names the widget rather than either of makepad's own
frames. No signature changes, no caller passes anything new, and the
existing tests needed no edits. Releases are logged from Drop rather than
end(), so giving a scope up by dropping it -- including a widget being torn
down, the case most likely to leak -- is reported exactly once on either
route.
StackNavigationView called the consuming back_pressed() whenever it was
Active, with no ownership check. A modal or pane opened over a pushed stack
view owns that press, but the view could consume it first and pop: the
wrong thing acts and the owner is starved, on one gesture. It worked only
because children are dispatched before the closure request, which is
precedence by traversal order -- the thing cancel scopes exist to replace.
A pushed view genuinely is what Back should pop when nothing is in front,
so it now holds a scope while Active and acts only when it owns the press.
Its five state writes route through a single set_nav_state that moves the
state and the scope together, acquired at the transition because ownership
is stamped before dispatch. The left_button and mouse-back-button paths
stay ungated: those are unambiguous clicks on this view, matching Modal,
which gates only back_pressed().
* Fix Escape and Back ownership across widget lifecycles
Allow gesture-specific scopes, preserve held Escape ownership across Back and focus changes, and suppress repeated Android Back dispatch without invoking Activity fallback first.
Release popup, modal, drag, and navigation scopes on every exit; support suspended navigation, isolate Pop actions, and finalize wide-window hide animations. Add focused ownership and lifecycle regressions.
Validated with 14 platform cancellation tests, 14 widget cancellation tests, Android Rust and Java checks, and a release modal Escape smoke test.
* Resolve cancel ownership from the active widget hierarchy
Bind widget scopes to their owners and resolve visibility and descendant priority only when Escape or Back begins. Retained inactive pages, collapsed controls, and unfocused windows no longer require application activation callbacks.
Preserve press ownership through repeats and release, suppress scoped or repeated TextInput Escape actions, and remove the StackNavigation cancellation activation API. Cover hierarchy, container, wrapper, focus, and gesture ownership regressions.
* Simplify cancel traversal and remove unsafe root lookup
* Reuse validated widget paths for repeated activity queries
* Remove PR-added cancellation tests and tracing
* Arbitrate the mouse back button with cancel scopes
The mouse's back button is the same navigation gesture as Android Back, but it
never received a cancel owner: handle_event clears press_owner for every event
and only restores it for Escape and BackPressed. owns_cancel was therefore false
for every scope while a MouseUp was delivered, so a widget could not gate that
button on ownership at all. The ones that tried had to fall back on ad-hoc
conditions -- "is my tab the visible one" -- which cannot express the thing that
actually decides it, namely that something else is in front.
Stamp a Back press for Event::MouseUp with the back button: in
resolve_widget_owner so widget-bound scopes are resolved against the hierarchy,
and in handle_event so ownership is settled before dispatch, exactly as for the
gesture itself.
StackNavigationView's mouse-back path is gated on that ownership to match its
back_pressed(). A pane or modal opened over a pushed view now takes the first
click and the view stays put; the second pops it. The left_button path stays
ungated, being an explicit click on the view's own header rather than a gesture
something in front of it could have a better claim to.
* Close a Modal on the mouse's back button
The back button is the desktop equivalent of the back gesture, and is arbitrated
by the same cancel scope, but Modal acted only on Escape, BackPressed, and a
click on its backdrop. A back-click inside the content did nothing at all, and
one outside it closed the modal only incidentally, as a background click.
Gated on ownership like the other two, so a modal opened over another one keeps
its place, and left inside can_dismiss so a non-dismissible modal still ignores
it. This is what lets a full-screen modal's content -- an image viewer, say --
respond to the back button without handling the gesture itself.
* Fold Modal's Escape and mouse-back checks under one ownership test
Same behaviour with one ownership test instead of two, matching how the other
cancel-gesture handlers read. Back consumption stays outside can_dismiss, so a
non-dismissible modal still blocks back-navigation for the widgets behind it.
- bundle_crate_secondary_dex: merge OUT_DIR/classes.dex from dependency
build scripts (robius-sms/trigger/ussd javac+d8 Java for manifest
receivers/services) into the APK as classesN.dex. Without it the
manifest declares BootReceiver/SmsReceiver/AccessibilityService that
are missing at runtime (ClassNotFoundException on boot).
- has_explicit_lib_target: a crate with src/main.rs containing app_main!
is an app, not a lib — generate the android wrapper ([lib] path =
src/main.rs) so the JNI entry (activityOnCreate) is linked. Fixes
UnsatisfiedLinkError for app crates that also ship src/lib.rs.
The generated android wrapper re-creates a standalone workspace and only
forwarded [patch.*] sections from the workspace root manifest, so deps
declared via [workspace.dependencies] + workspace = true failed to inherit
in wrapped crate builds. Extract the [workspace.dependencies] section the
same way patches are handled and inject it into the wrapper manifest.
- makepad_test/runtime.rs: forward NIGIG_TEST_MODE from host env to the
Android app via 'am start' intent extra; add wait_timeout (60s) used by
wait_visible/wait_hidden/wait_count; make query_widgets tolerant of
snapshot timeouts; grant READ_CONTACTS during adb setup
- makepad-platform android_jni.rs: read makepad.NIGIG_TEST_MODE intent
extra and surface it as the NIGIG_TEST_MODE env var via apply_studio_env
- cargo_makepad compile.rs: support verbatim custom AndroidManifest.xml in
addition to the templated variant
- makepad-xr xr_root.rs: add ortho camera controls (ortho, ortho_height,
min/max), derive Debug on XrCamera
- docs: ANDROID.md and DESKTOP_VISIBLE.md for makepad_test
A package whose bin name differs from the package name (apps/finance: finance) no longer
fails at packaging; the bin is resolved from cargo metadata, default-run or --bin, and the
minified JS copies are written after their directories exist.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WV6BzHQiJEvvK9EPc1d4ks
Apps ask the hub for a recognizer or a voice and get one; where it runs is
the hub's decision. AiHub::start_stt / start_tts return poll-driven
sessions shaped like the chat session. The Auto ladder is Whisper/Kokoro in
this process (weights present, machine election), on the machine node over
loopback, on a LAN node, else the OS engine; SpeechReach::Local is the
"don't reach out" knob. Audio always comes back as PCM: the app owns the
device.
Three layers:
- makepad-ai-speech is the whole speech model family, engines only.
libs/voice (Whisper + Silero VAD) folds in as the `whisper` and `vad`
modules next to kokoro and indextts, each a cargo feature; the Apple
bridges and the Speaker/VoiceTranscriber selection leave it.
- makepad-system-speech (new) is the OS speech services as blocking fns:
Apple SpeechAnalyzer/AVSpeechSynthesizer via Swift, Windows.Media.Speech*
on the vendored bindings, Android SpeechRecognizer/TextToSpeech through
MakepadSpeech.java (API 26 floor), espeak-ng on Linux. It models the two
STT shapes honestly: PCM in (Whisper, Apple) versus an engine that owns
the microphone (Android, Windows), with capabilities the caller reads.
- the hub grows speech sessions, in-process Whisper/Kokoro workers with the
residency election, a `whisper` wire backend (stt domain, registry entry
pinned to ggerganov/whisper.cpp) so a Mac can serve a Quest, and a
`language` field on the generate request.
Consumers: the Window voice input runs on an STT session and switches to
engine-mic mode when the recognizer owns the microphone; converse's
SpeechOutput is a lazily started TTS session plus a pump thread; route
drops its private speech copy for converse; vj's lyrics fallback and the
alignment bakes call the engines directly.
Verified here: speech-roundtrip through the real sessions (Apple voice in,
in-process Whisper on Metal out, 4.3% WER); system-speech-test TTS->STT
verbatim; hub/converse/system-speech unit tests; msvc, aarch64-android and
linux-gnu cross-checks; Java against android-34. Windows, Android and Linux
bridges are compile-checked only.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Squashed from work:
- platform: native file and save dialogs, in-house on all three desktops
- platform: file dialogs on Android and iOS, and unbreak the Android build
Android builds passed `-C prefer-dynamic` unconditionally, so Rust shipped
`std` as a separate `libstd-<hash>.so`. That library is a rustup prebuilt whose
LOAD segments are only 4 KB-page aligned (`p_align 0x1000`), so it can't be
mapped on the 16 KB-page devices Android 15 allows. Google Play requires apps
targeting API 35+ to run there, so release apks were failing that bar even
though `libmakepad.so` itself was already linked with 16 KB alignment.
Only debug builds keep `prefer-dynamic` now, where the faster incremental
relink is worth having and nothing ships. Everything else links `std`
statically, which drops the separate library entirely and leaves a single
NDK-linked, 16 KB-aligned `.so`. The aab path already did this.
* android oes video zero-copy and gles shader fixes
* regenerate windows-rs by windows-strip
* fix windows video freezes with MF on an MTA worker
* regenerate windows-rs by windows-strip
* MTA MF video, COM notify, YUV texture reuse
* add local video file playback support to video-player example
* NV12 Metal present, seek warm-up gate, YUV full range
* fix Linux GStreamer video: A/V mute, HLS prepare, async teardown
* no-op SelectVideoTrack/SelectAudioTrack on non-Linux backends
* Linux ALSA/Pulse: bigger buffers, fix resample setup, report device rate
* fix some warnings
* Move XInput/DirectInput device discovery off the UI thread
* fix GLSL unpack4u8 for GLES 3.0 (#version 300 es)
* Linux GStreamer: DMA-Buf NV12 OES zero-copy, optional GLMemory path
* Linux MediaPlugin: DMA-Buf NV12 and GLMemory zero-copy present APIs
* Add Windows SourceReader DXGI NV12 zero-copy video path
* fix build error
* fix GLES: add highp precision for sampler2DArray in Linux shaders
* playback speed support for android
---------
Co-authored-by: jasonqiu <jasonqiuchen@outlook.com>
Co-authored-by: jasonqiu <jasonqiu@futunn.com>
* TextFlow: fix inline `<code>` spans sagging below the baseline
finish_row_center centered every walk by its own height, so a code run's
shorter walk got a larger downward shift than the surrounding prose under
`RowAlign.Center`. That undid TextFlow's baseline_shift: inline `<code>`
spans sat a few px below the line's baseline, and their descenders poked
out of the bottom of the code box.
* FinishedWalk now carries an optional `align_height` that text runs set
to their line style's height, so every text run on a row receives the
same centering shift and stays on the baseline. Also fixes sub- and
superscripts drifting under `RowAlign.Center`.
* The per-style metrics probe now caches descenders too, since we need
the full line height (ascender + descender) to compute `align_height`.
* Html/Markdown: make the fixed/code font size scale configurable
Replaces the hardcoded 0.85 `FIXED_FONT_SIZE_SCALE` consts with a
`fixed_font_size_scale` live property on TextFlow (default 0.85), so
apps can tune how much smaller `<code>` text renders than the prose.
* cargo_makepad: don't include `resources/android`/`ios` on every platform
Runtime asset bundling copied each crate's entire `resources/` tree into
every package, so `resources/android/` (manifest template, launcher icon
mipmaps) shipped as dead weight inside APK assets and Apple bundles, and
any `resources/ios/` content would ship on Android too. Those dirs are
platform-specific, so only their own platform should bundle them.
* Add `cp_all_skip_top()` to `makepad-shell`: like `cp_all()`, but skips
top-level entries by exact name.
* Android (APK and AAB staging): bundle `resources/android/` minus the
packaging inputs `AndroidManifest.xml.template` and `res/`, which
already reach the package via the generated manifest and the aapt
`res/` pipeline; skip `resources/ios/` entirely.
* Apple bundles: skip `resources/android/`, keep `resources/ios/`.
* Support standard keyboard navg shortcuts/keys in TextInput
Implement platform-standard TextInput navigation and deletion behavior,
including Home, End, PageUp, PageDown, word movement, line/document
boundaries, and Shift-based selection.
* Use Apple Option/Cmd conventions on Apple targets
* Use Ctrl conventions on non-Apple targets
* Web accepts both shortcut styles for now, since we don't have a way
to query the host OS from within a makepad web env.
Also, be extremely careful to ensure that we respect Unicode grapheme boundaries
when doing all the selection/navigation logic.
Fix `Delete`, which was erroneously handled before.
Add lots of missing keys in Linux X11 & Wayland backends, e.g.,
Home, End, Delete, Insert, PageUp/PageDown, and arrow keys
* Add `CropToFill` image fit variant, improve ImageFit docs
This allows you to easily achieve the "centered cropped fit" that most apps
want for things like avatars or small thubmnails that get masked.
* Detect and support hardware keyboards, distinguish from soft/virtual kbd
Mimic desktop behavior on mobile systems as much as possible.
This is esp important for tablets like iPad OS where you're more likely
to have a real physical keyboard attached.
For iOS:
* Arrow keys and Home/End/PageUp/PageDown navigate and auto-repeat
at the system-defined rate (connected via `UIKeyCommand`)
* Cmd+Enter to submit a `TextInput` and Cmd+C/X/V clipboard shortcuts now work.
* Ensure the pop-up diacritic/accent menu is properly placed using a hidden
`UITextInput` native widget, which acts as a sort of "proxy"
* Proactively drain `ShowTextIME` after each draw so the IME position will be
properly updated after each keystroke.
* Importnatly, don't mark the IME dismissed when a hardware keyboard is attached.
For both iOS & Android:
* Add a `has_physical_keyboard()` detection mechanism across both backends,
and fix platform-specific key repeat behavior
For Android:
* Ensure clipboard cut/copy works using the same Ctrl shortcuts (API 26+)
Soft/virtual keyboard/IME changes:
* For multiline TExtInputs, a soft keyboard Enter/Return key will always just
insert a new line, to avoid complexity with keyboard shortcut cfgs.
* CJK keyboard character selection should also be properly positioned now
* minor optimization to avoid re-setting IME pos if it didn't change
* Extend support for system bar appearance to iOS too
* cargo_makepad: fix default icon behavior for iOS
Icons need to not be modified by cargo_makepad if they're already
in the proper iOS-expected format, otherwise they'll end up with
some kind of extra black border around the icon, which looks bad.
* Dock: avoid ID collisions in drag/drop; never delete dock root in unsplit_tabs
* Clean up and further harden dock logic around splitting/dragging
* cargo_makepad: Android App Bundle builds, API 26 support, stable toolchain
Overhaul the Android build pipeline. Three related build-tooling
changes that share compile.rs/sdk.rs and so are committed together.
Android App Bundle (.aab) support — required for Google Play uploads:
- New `build-aab` command: compile resources with aapt2, link a
proto-format APK, assemble the base module, run bundletool, and sign
with jarsigner.
- New `keystore-create` command wrapping keytool, with a reusable
keystore sidecar file; new `--keystore*`, `--no-sign`,
`--version-code`, `--version-name` flags.
- Version codes may be explicit or auto-generated as a monotonic
YYYYMMDDHH UTC integer.
- Read app id, version, and signing metadata from
`[package.metadata.packager]` / `[package.metadata.makepad.android]`
in Cargo.toml; support a custom AndroidManifest.xml template.
- Upgrade the bundled TOML parser for the dotted keys, inline tables,
and multi-line strings those metadata sections use.
- Download bundletool and copy jarsigner/keytool/aapt2 into the SDK.
minSdkVersion 26:
- Lower the default Android minimum SDK from 33 to 26 and track the
target SDK (35) separately, emitting minSdkVersion and
targetSdkVersion independently in the generated manifest; add a
`--min-sdk-version` override.
Stable Rust toolchain:
- Build Android and iOS on stable instead of nightly. tvOS still needs
nightly for `-Z build-std`, so the channel is resolved per target.
- Add `ensure_rust_toolchain_installed` (install only when missing).
* Android: load newer NDK symbols at runtime to support API 26
With the minimum SDK lowered to 26, NDK entry points that only exist
on newer API levels can no longer be declared with `extern "C"` —
doing so breaks `dlopen`/startup on API 26-28. Resolve them at
runtime instead:
- amidi_sys: lazily `dlopen` libamidi.so (API 29+) into a cached
vtable; the wrappers degrade to error/zero returns when the library
is absent on older devices.
- android_jni: `dlsym` the AChoreographer vsync callbacks, gated on
the running API level.
- ndk_sys: drop the `extern "C"` declarations for
`ANativeWindow_setFrameRate` and the Choreographer callbacks;
android.rs drops the now-unused frame-rate call.
- MakepadActivity: guard `setInitialSurroundingSubText` (API 30+) and
`layoutInDisplayCutoutMode` (API 28+) behind version checks.
- android_jni: the fallback render-loop thread now exits cleanly when
the app is torn down.
* Android: automatic and app-controlled system bar appearance
Add a way to control the tint of the status and navigation bar icons,
fixing white-on-white (invisible) icons when an app draws a light
background under a system dark-mode theme.
- New `Cx::set_system_bar_appearance(SystemBarAppearance)`. The default
`Auto` mode picks dark or light icons from the window background
luminance; `DarkIcons`/`LightIcons` force the choice.
- The `Window` widget resolves the setting each event cycle — for
`Auto`, the Rec.709 luma of `pass.clear_color` — and emits
`CxOsOp::SetSystemBarDarkIcons` only when the resolved value changes.
- On Android this drives `WindowInsetsController.setSystemBarsAppearance`
(API 30+) or the `SYSTEM_UI_FLAG_LIGHT_*` flags (API 26-29). The tint
is re-asserted after fullscreen toggles, since the legacy path
rewrites the whole `systemUiVisibility` bitmask.
* Android: fix soft-keyboard handling and edge-to-edge insets
Several related window-inset and IME fixes, mostly affecting devices
that are not edge-to-edge (Android versions before 15).
- Report safe-area and IME insets as the overlap with the render
surface, not the raw window-edge insets. On a non-edge-to-edge
window the surface already sits inside the system bars, so the raw
insets double-counted — leaving oversized gaps around content and
above the keyboard.
- Also drive safe-area insets from `onGlobalLayout`, so the app is
inset correctly from launch instead of drawing under the status bar
until the first keyboard show or rotation.
- While the keyboard animates, treat the `WindowInsetsAnimation`
callback as the authoritative per-frame inset source and have the
layout-driven callbacks defer to it. Read target IME visibility from
`getRootWindowInsets()` so a show animation is not misread as an
instant dismissal.
- Only reconfigure the Java IME when the `TextInputConfig` actually
changes, instead of on every show.
- `KeyboardView`: compute and apply the content shift at keyboard-show
event time, removing a one-frame lag and a tail-end jump; only
reconcile post-draw when the focused field actually redrew.
- `Modal::close()`: skip the focus revert when the modal is already
closed — it was stealing focus from a just-tapped text input and
causing a first-tap keyboard flicker.
- Hide the keyboard via `WindowInsetsController.hide(ime())` on API 30+.
* platform: don't panic posting actions during shutdown
post_action no longer unwraps the global action sender. It now
silently drops the action if the sender mutex is poisoned, no Cx
sender is installed, or the receiver has been dropped during app
teardown, and only raises the UI signal when the send succeeds.
(Also shortens an over-long field doc comment in cx.rs; no behavior
change.)
* cargo-makepad: link std statically in AAB builds (16 KB page-size fix)
`-C prefer-dynamic` ships std as a separate, 4 KB-aligned libstd.so that
fails Play's 16 KB page-size rule. AAB builds now link std statically;
APK/dev builds keep prefer-dynamic. Also documents {min_sdk_version} in help.