Commit graph

7 commits

Author SHA1 Message Date
Kevin Boos
b5bd9bc6b9
Ten fixes from moving an app onto current dev: macOS drawable/resize, the UI signal broadcast, internal drag on Linux, and log noise (#1239)
* Button: add `label_align` to center a wrapped label

`Button::draw_walk` passed `Align::default()` to `draw_text.draw_walk`, so
a label that wrapped onto more rows left-aligned them under each other even
when the button itself centered its content, and no script property could
reach that argument.

* New `#[live] label_align: Align`, mirroring the one `TextInput` already has.
* Defaults to left, so every existing button draws exactly as before.
* Pair it with a `Fill`-width `label_walk` to give the rows room to move.

* macOS: don't paint into a drawable the layer has since outgrown

The prefetching `DrawableWorker` hands back a drawable that `nextDrawable`
acquired on the previous beat. A frame that straddles a resize therefore
attaches a texture of the old size to a viewport derived from the new one.

* moving a window between displays of different DPI drew the whole UI at
  the old scale, and it stuck: a dpi change dirties the pass exactly once
* dragging a border fast left the strip the old texture didn't cover
  unpainted, which macOS shows as magenta

Check the invariant where the drawable is consumed: a texture whose size
isn't the layer's `cal_size` is dropped and one is acquired on this beat,
the way the pre-worker path did every beat. The pool was just rebuilt for
the new size, so that acquire doesn't block. Traced on the `present` topic.

* Window: don't put an app icon in the caption bar by default

`AppIcon` falls back to a generic placeholder tile for any app id makepad
ships no artwork for, so every third-party app got a meaningless icon next
to its title, and an off-centre title with it.

* `AppIcon` gains `visible`, which it had no way to express before
* the caption icon defaults to hidden; apps opt in with
  `caption_icon +: {visible: true}`

* Quiet the startup and per-decode log spam

A plain run printed ~1500 lines before anything happened.

* `zune-qoi` was the only zune crate with `log` in its default features,
  and cargo unifies that onto `zune-core`, so every zune decoder logged
  per image. zune-core's macros became real logging in this tree, so what
  used to be inert now floods the log
* memory budget, task-pool priority/summary and the Metal retained-upload
  budgets move onto the `MAKEPAD_TRACE` topics this tree added
  (`memory`, `pool`, `gpu.upload`)
* drop the studio-websocket line, which only says a disabled thing is off

* Make the UI-hang sampler opt-in

It started with every `Cx`, so a shipped app carried a thread waking ~16
times a second forever, and any stall over 250ms got the UI thread
suspended once per sample while its stack was walked.

`MAKEPAD_UI_HANG_MS` is now the switch as well as the threshold. Unset, no
thread starts and the phase guards see a null registration, which is a TLS
read and a null check.

* Wake the event loop from render workers without raising the UI signal

`Event::Signal` means "a worker has something for you" and is dispatched to
the whole widget tree. The submitter, the instance allocator and the
drawable worker raised it after every commit, so an app painting at 120fps
walked its tree 120 extra times a second. Measured in robrix: 119 signals
against 111 repaints, down to ~0.3 per frame.

They only ever wanted the loop awake, so give them `wake_ui_loop()`, which
is what `set_ui_signal` already called underneath. A dirty pass is what
keeps the paint clock armed, so nothing depends on the flag to get painted.

* Compare the resident instance bytes instead of hashing them

`immediate_payload_hash` FNV'd every byte of every dirty draw call to skip
the upload when nothing changed. That suits a few big payloads, not a 2D
frame: robrix scrolls ~1090 draw calls of ~110 bytes, and the hash cost
2.3ms a frame in a debug build to skip ~12% of 110KB of uploads.

Instance buffers are StorageModeShared, so the resident copy can just be
compared. `memcmp` stays fast in an unoptimized build, and an exact
comparison can't collide into a stale frame the way a hash can.

* Install a platform stylesheet only when an app asks for one

`current()` picked "ios"/"android" straight off `OsType`, so any app built
for a phone was silently restyled: ~270 theme tokens including the fonts,
over whatever the app had already set.

Worse, it only half-landed. `apply_theme` runs from `widgets_mod` but
`apply_widgets` runs from `script_mod`, so an app that calls the
`theme_mod` + `widgets_mod` pair got the mobile palette with desktop
metrics. Every in-tree user already calls `install` or sets
`MAKEPAD_WIDGET_STYLE`, so that variable is now the only implicit route.

* Let an internal drag deliver its pointer events on Linux and wasm

Moving internal drag handling into shared code changed it in two ways that
the macOS and old X11 paths never had, and a dock tab shows both.

The pointer event was replaced by the drag event rather than followed by
it, so no widget saw the `MouseUp`. `Tab` sets `is_dragging` on FingerMove
and clears it only on FingerUp, so a tab could be reordered once and then
never dragged again. Dispatch the pointer event first and append the drag
one, with a flag so that dispatch doesn't produce the drag event again.

A release that never moved after `start_dragging` also produced no Drop and
no DragEnd at all, so `Dock` never cleared `dragging_tab` and kept painting
the ghost. `Tab::min_drag_dist` has no default, so a press, one motion and a
release reaches it. Every other backend ends the drag unconditionally.

* Split the UI signal so makepad's own queues don't broadcast Event::Signal

`set_ui_signal` was the one wake for everything, and every platform loop
answered it by running makepad's handlers AND broadcasting `Event::Signal`
to the whole tree. So termination, the network runtime, live reload and
every pool completion (label shaping, per frame) woke every widget.

* `set_internal_signal`: the loops run their handlers and don't broadcast
* `TaskPool::submit_internal`: a job whose result makepad polls at draw
* `Event::Signal` is documented, and the loops treat the app flag as a
  superset of the internal one, so nothing left on it can regress

The scheduler keeps the app signal on purpose: `service_scheduler` re-arms
the platform timer from `call_event_handler`, which only the app half runs.
Media device changes still go through `SignalToUI::set`, whose instance API
is app-facing; they are hotplug-rare, so splitting that is left alone.

* Harden the drawable re-acquire, the internal drag and the opt-in sampler

Follow-ups from reviewing the five commits above.

* the resize re-acquire only runs while the drawable pool has a free slot.
  Exhausted, `nextDrawable` blocks the UI thread on the compositor, which is
  what the worker exists to avoid; skip the beat and stay dirty instead
* the byte compare no longer skips an item the GPU has evicted, which would
  leave it invisible in a pass that then repaints forever
* the internal drag suspends its items across the pointer dispatch instead
  of holding a flag. An unwound dispatch now ends the drag rather than
  wedging it for the life of the process, and a widget that starts a new
  drag from that dispatch keeps it instead of tripping "start drag twice"
* `tests/ui_hang.rs` opts the sampler in, since it is the thing under test
2026-09-18 09:06:31 +02:00
Admin
a4ea2536a4 platform: topic hunks the per-commit assembly could not place, the Sep 2–15 dev PRs (#1208–#1236) as adapted to this tree, and the zero-warning chore
code_editor/Cargo.toml                          |     1 -
 code_editor/src/lib.rs                          |     3 -
 draw/src/cx_2d.rs                               |    83 +
 draw/src/cx_draw.rs                             |    43 +
 draw/src/draw_list_2d.rs                        |    22 +
 draw/src/geometry/geometry_gen.rs               |     7 +-
 draw/src/image_cache.rs                         |    51 +-
 draw/src/lib.rs                                 |     1 -
 draw/src/shader/draw_text.rs                    |    40 +-
 draw/src/shader/mod.rs                          |     1 -
 draw/src/text/fonts.rs                          |     2 +-
 draw/src/text/mod.rs                            |     1 -
 draw/src/text/slug_atlas.rs                     |     2 +-
 draw/src/turtle.rs                              |  3469 ++++-
 draw/src/vector/triangulate.rs                  |   378 +-
 libs/error_log/src/lib.rs                       |    17 +-
 platform/network/src/backend.rs                 |     6 +
 platform/network/src/backend/apple/http.rs      |     2 +-
 platform/network/src/http_server.rs             |    15 +-
 platform/script/derive/src/derive_scriptable.rs |    19 +-
 platform/script/src/lib.rs                      |     4 +
 platform/script/src/shader_calls.rs             |    92 +-
 platform/script/src/shader_hlsl.rs              |     9 +-
 platform/script/src/shader_metal.rs             |    18 +-
 platform/script/src/shader_wgsl.rs              |    12 +-
 platform/script/tests/hook_scope.rs             |     8 +-
 platform/src/action.rs                          |    12 +-
 platform/src/app_main.rs                        |   110 +-
 platform/src/cx.rs                              |   466 +-
 platform/src/cx_api.rs                          |   368 +-
 platform/src/draw_list.rs                       |  2598 +++-
 platform/src/draw_pass.rs                       |    35 +-
 platform/src/draw_vars.rs                       |   103 +-
 platform/src/geometry.rs                        |   588 +-
 platform/src/gpu_texture.rs                     |     2 +-
 platform/src/id_pool.rs                         |    71 +-
 platform/src/lib.rs                             |    26 +-
 platform/src/log.rs                             |   111 +-
 platform/src/os/apple/apple_game_input.rs       |     6 +
 platform/src/os/apple/apple_sys.rs              |     1 +
 platform/src/os/apple/macos/macos_app.rs        |   384 +-
 platform/src/os/apple/metal.rs                  |  3347 +++-
 platform/src/os/cx_native.rs                    |     5 +-
 platform/src/os/cx_shared.rs                    |   202 +-
 platform/src/os/gpusim/event_loop.rs            |    24 +-
 platform/src/os/gpusim/mod.rs                   |     8 +
 platform/src/os/gpusim/raster.rs                |    11 +
 platform/src/os/linux/opengl.rs                 |   856 +-
 platform/src/os/linux/vulkan.rs                 |   752 +-
 platform/src/os/linux/vulkan_linux.rs           |     4 -
 platform/src/os/linux/wayland/linux_wayland.rs  |    15 +-
 platform/src/os/linux/wayland/opengl_wayland.rs |    67 +-
 platform/src/os/linux/wayland/wayland_state.rs  |    37 +-
 platform/src/os/web/web.js                      |  1409 +-
 platform/src/os/web/web.rs                      |   212 +-
 platform/src/os/web/web_gl.rs                   |   284 +-
 platform/src/os/web/web_worker.js               |    76 +-
 platform/src/os/windows/d3d11.rs                |  1323 +-
 platform/src/remote.rs                          |  1297 +-
 platform/src/retained_instances.rs              |     3 -
 platform/src/script/res.rs                      |   245 +-
 platform/src/sploded.rs                         |    59 +-
 platform/src/texture.rs                         |   416 +-
 platform/src/thread.rs                          |  2816 +++-
 platform/src/thread/ui_hang/linux.rs            |     2 +-
 platform/src/thread/ui_hang/macos.rs            |    22 +-
 platform/src/thread/ui_hang/native.rs           |     3 +
 platform/src/thread/ui_hang/windows.rs          |     2 +-
 platform/src/web_socket.rs                      |    45 +-
 platform/src/window.rs                          |   129 +-
 platform/tests/texture_lifetime.rs              |   143 +-
 platform/video/src/stream_debug.rs              |     2 +-
 platform/video/tests/stream_codec.rs            |    85 +-
 widgets/derive_widget/src/derive_widget.rs      |     4 +-
 widgets/src/animator.rs                         |   138 +-
 widgets/src/combo_box.rs                        |    10 +
 widgets/src/desktop_style.rs                    |     4 +-
 widgets/src/drop_down.rs                        |    96 +
 widgets/src/font_policy.rs                      |    25 +
 widgets/src/grid.rs                             |     1 +
 widgets/src/image.rs                            |     3 +
 widgets/src/lib.rs                              |    18 +-
 widgets/src/map/archive.rs                      |   544 +-
 widgets/src/map/geometry.rs                     |    34 +-
 widgets/src/map/label.rs                        |    48 +-
 widgets/src/map/tile.rs                         |  6890 ++++++---
 widgets/src/map/tile_draw.rs                    |     2 -
 widgets/src/map/view.rs                         | 17896 ++++++++++++++--------
 widgets/src/menu_bar.rs                         |    18 +-
 widgets/src/screen_cap.rs                       |   513 +-
 widgets/src/slider.rs                           |     6 +
 widgets/src/splash.rs                           |   280 +-
 widgets/src/tweaker.rs                          |   221 +-
 widgets/src/view.rs                             |   105 +-
 widgets/src/widget.rs                           |     5 +-
 widgets/src/widget_async.rs                     |   269 +-
 widgets/src/window.rs                           |   601 +-
 widgets/src/window_voice_input.rs               |    17 +-
 98 files changed, 38159 insertions(+), 12677 deletions(-)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 13:40:33 +02:00
Admin
4945f1873b platform: rename the CPU simulated-GPU backend from headless to gpusim
Squash of 1 work commits (Sep 12–12):
  e74b919  platform: the CPU simulated-GPU backend is `gpusim` — the word "headless" now means only window-less

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 13:40:28 +02:00
Admin
b53ea0b30a platform: macOS display-link, App Nap, waker, IME-adjacent event loop
Squash of 2 work commits (Sep 9–12):
  8d851ef  platform: per-draw alpha blend, macOS waker, texture lifetime, file drop
  cc2fa8f  platform: the Metal display link is gone; the hang line prints its tick deficit; hidden instances refuse App Nap

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 13:40:24 +02:00
Admin
2e27ce2ff1 platform: retained draw lists, shared publications and GPU residency (DL-0..DL-5)
Squash of 27 work commits (Sep 3–12):
  aa907ca  platform: a frame trace on both desktop backends, and a window that cannot present stops ticking at 600 Hz
  e3abf4d  map: the hosted-tile cache keeps the same ~2x-visible margin as the local one — a budget pinned at the visible set evicted the trailing edge of every pan on the next frame and refetched it a moment later
  8d542fe  platform: a child pass orphaned by its attaching draw list is no longer painted — the window's gauss_scene pass stayed a live_with_parent child after the map went flat and re-encoded a frozen 400-item list every pan frame with stale geometry ids (new tile meshes × old instance counts, tens of millions of triangles into a texture nobody read); make_child_pass records the recording list + redraw id, stale passes are skipped, a cached View re-attaches on a cache hit; tests for the orphan gate and the pool generation contract
  bb49fe6  map + platform: retained per-tile draw lists — each resident tile owns one DrawList2d per carto pass (fill, casing, stroke, icon, icon-high, shadow) and the label glyph batches are retained the same way, recorded when the bake, LOD ring, fringe/icon gates, flat/tilted or clip change and re-attached otherwise; a pan/zoom/tilt frame pushes this frame's uniforms onto the retained calls (DrawVars::update_uniforms_on_area, resolved slot table) and uploads zero instance bytes; the tilted per-pass depth is a pass_depth uniform; a held list's zbias resolves at entry (zbias_hold in every backend); the shimmer heartbeat patches shiny_time in place without a redraw; a freed/reused sub-list id is skipped by every draw-tree walker and the mask list re-records empty on the flat transition (contract test). Web pan tail 1,098 → 20 MiB/s, flat pan 2.4 → 0.43 MiB/frame; Metal grabs within the run-to-run noise floor
  313265d  Studio code atlas: geometry code views, live filter, 3D size lens, lanes as terminals
  9c4e0cc  Studio code atlas: performance round — retained uploads, worker labels, exact search, no forks
  7235d7e  Studio code atlas: stall fix, GPU working set, lens hard switch, filter masks, parallel index
  56a6da5  platform: per-pass GPU counter timing on Metal; retained publications replace in place
  72e2443  platform: present-path trace (1 Hz cause histograms), bounded drawable wait and retirement on macOS
  1c5d583  platform: bounded retained maintenance on empty paint beats; republish actual backend debt
  edfed73  platform: retained residency high/low water and hysteresis; no distance eviction without pressure
  acab6a0  platform: critical upload class serves present-blocking items first; identical immediate re-records upload nothing
  906c774  platform: uniform_range on DrawVars and patch_retained_uniforms on retained draw lists
  c29031c  platform/draw/widgets: heap-keyed script resources and RecordingBuffer draw items — the files today's commits depend on
  cd0964f  platform headless: homogeneous near-plane clipping before the perspective divide
  61d424d  platform: release retained bindings of released textures so pool evictions complete
  a00287a  platform: texture-tile cache support — per-item instance ranges, painted pass receipts, display-dpi pass uniform, retained render targets, present gate on the drawable pool
  74b63be  platform: retained upload floor reverted, unconfirmed presents counted
  c03fcc5  platform: tile-cache round 3 support — O(1) demand on re-recorded lists, evictions counter, allocated_size, lost-button release, Vec2d::round
  e515d75  platform: shared instance publications — the DL-0/DL-1 contract, additive beside the retained path
  142a337  platform: shared instance publications — close the seven review items (DL-1b)
  6811a19  platform: Debug for SharedInstances, WeakSharedInstances and PublishReceipt
  c061e47  platform: Metal draws are resident by construction — the hole path and its gates are gone (DL-2)
  0bdbb29  platform: drop the unreachable InstancesNotResident present cause
  de3c868  platform: `drawlist` trace names the holder of a stale draw-list id; the per-frame upload line moves to `gpu.upload`
  721c3d8  platform: publication backends — Metal per-publication backings, lease-keyed uniform ring, receipts on every backend, Vulkan draws attached items (DL-3)
  393de54  platform: integrated deletion — the draw-list system is generic again (DL-5)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 13:40:23 +02:00
Admin
48e7a01ec9 draw: geometry, shaders, WGSL, fonts, turtle/layout
Squash of 10 work commits (Sep 2–11):
  120b7e2  score view: the engraver as a shared library, with drum and pitched score builders
  09b41a8  fonts: FontSet and FontPolicy — one application choice, selected-only loading, a font-assets manifest
  6981e90  fonts: manifest generated from the chains, app-level font assets, a symbol fallback, deprecated i18n aliases
  77d9138  wm: the module contract and the first in-process app — sheets in a tile, in an isolate of its own
  55a3810  platform: typed compact vertex formats and u16 indices
  83a8d4f  fonts: the web demos start with the Latin set — CJK and emoji faces load on the first glyph that needs them
  1980c24  platform: a draw call whose geometry id went stale is skipped, not drawn with whatever mesh now sits in the reused slot — the runaway triangle count that took a web map pan to 1 fps; reported with a power-of-ten backoff, never per frame
  a75fe91  layout: extend turtle sizing and add Grid
  4429551  draw, widgets: text clips by the list clip; GaussChain; map colour roles
  6e02468  draw: restore Cx2d::set_current_pass_dpi_factor (raster density) beside the display-dpi setter

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 13:39:02 +02:00
Admin
874374635f widgets: glass, dock, tweaker, themes, code_editor, phone shell
Squash of 36 work commits (Sep 1–12):
  176433a  tweaker: click-again climbs the pick — the container under the children is reachable
  97e9572  speech: one STT/TTS API on every platform, through the ai-hub
  8ea3684  widgets: EventOrder reachable from the DSL; DataGrid hit-tests where it was drawn
  0fd1ea2  route: demo profile — native/demo features, side-panel and provisioning seams, hosted tiles, HTTP nav client
  cf4c84c  keys: F10 is the assistant — the exploded-view debugger moves to Shift+F10, the screen recorder to Ctrl+F10
  126d8c9  route: the demo profile runs in the browser — merged panel draw, platform clock, unavailable backends tolerated
  e21db96  route: demo review fixes — route origin, rain lifecycle, hosted route validation, request context, provisioning
  c24c206  aichat: the Window overlay — F10 in every standalone app, the in-process port, the /ai bridge routes, sheets as the pilot
  dbe43bd  wm + widgets: the AI panel on the left, pushing the body in
  5184340  platform + vj + map + files + widgets + image_tiles: the runtime owns one warm two-lane task pool — jobs never spawn threads
  697215e  route + converse + example-map: every worker comes from the runtime pool or a start-up worker
  862f3bd  asset widgets + chat ui + render: fan-outs and jobs on the runtime pool, the transcript read without a lock on draw
  976ea0e  tweaker: Shift+F10 toggles it on every platform (KeyEvent::is_tweaker_toggle, one call site; the web page swallows exactly Shift+F10 so the browser never sees it); the exploded z-layer view has no keyboard shortcut any more — it is a button in the tweaker
  4e8e4cd  flow-ui: the design pass — menu bar and toolbar with the total run bar, continuous zoom through the draw-list view transform with pointer remapping, dark checker canvas with grid steps, shadowed cards with icon labels and port icons, glowing wires, per-node progress bars, full-bleed image cards, palette cards you drag out, the fab edit controls in the inspector, a template picker behind New, model pickers from the hub; MenuBar widget in the shared crate
  075e1a7  flow-ui: pickers filled from the hub for image and text nodes, popups anchored through the canvas transform, labelled face controls, add_style explains itself, cards resize from a grip with size: vec2 kept in the file, full-bleed pictures, a click anywhere on a card selects it and still reaches the face, no remount on layout-only edits, panels float over the canvas
  a50750f  flow-ui: Flows, Running and Palette as their own rounded panels with splitters, the inspector and source pane likewise, columns resizable; gaussian frame shadows; keys and IME reach the focused face field through the canvas transform
  43302a6  flow-ui: every card owns a draw list and draws in z order, selection brings it to the front; and the design review's findings — every event kind remapped through the camera, run events keyed by run id, no remount mid-run, an input journal that survives a failed PUT, terminal states reconciled, the total bar from the planned node set, isolate ownership on instance change, popups retired before an isolate is freed, the Ask face answers on a button, the menu bar navigates by keyboard, no per-frame allocation in the canvas draw
  4ee4f4c  flow-ui: the resize path sets walks and fits through typed setters, never a script apply from the main VM on an isolate's widget — a failed apply had left a freed script object behind and wedged every frame; a resized card fills its picture box, clips its face and lets the last flexible element take the height
  cff15ac  widgets: a fab number field drops a label that cannot fit instead of crushing it to a dot
  24c927a  flow-ui + widgets: every dropdown is the searchable ComboBox
  a6c5f15  widgets: FabValueInput honours visible, so the seed picker's random mode hides the number field
  1181a3b  flow + flow-ui + widgets: every creator pipeline is a template — 55 templates in six groups (Image, Video, Audio, 3D, Vision & text, Utilities), all evaluated and engine-exercised in tests; the New picker, the flows.templates tool and the palette group the same way; the Templates menu shows them under group headings, and a menu taller than the window scrolls
  f8b9a67  widgets: preserve numeric edit completion and menu focus
  ed5f2e2  Add hotloadable OS themes and preserve widget state across style changes
  f1d3b39  Center resized app recordings on a fixed black canvas
  915fcae  Remove icon rim highlights and align compact home tile contents
  bfa7805  Keep terminal palettes theme-aware and resize above mobile keyboards
  7535ce8  Fix workspace build regressions (#1220)
  2233cbc  Replace legacy Studio with docked and canvas agent workspace
  708aa9f  code_editor: range views, anchors, prepared documents, read-only, tab stops
  0eae276  widgets: capture Studio evaluation feedback and recordings
  487c602  widgets: let Studio pump dock bodies across presentations
  c5adb93  Studio code atlas: settle-line diagnostics, index progress, chrome fades, exact search budget
  ee9ab46  widgets: every screen capture lands in the repo's local/screencap, named by app
  dcc9673  draw, widgets: the phone shell's glass, hosted-view and overlay support, app icons for the new apps
  2fbc679  wm: preserve app caption controls and add Scope to the launcher

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 13:38:48 +02:00