The handle mixed the hitbox-local drag origin with window-space
drag-move positions, so the first move snapped the ratio to a clamp
boundary (a panel suddenly grew and further drags did nothing). Drags
are now incremental window-space deltas applied to the freshly-read
ratio; drag-move routing is filtered to the owning split container so
nested splits no longer double-apply with wrong geometry; pair extent
excludes the divider itself so the boundary tracks the pointer 1:1.
The strip handed the drag to the dock area via cx.emit, which is
deferred — the dock's drag state was created a dispatch too late, so
the hovered target was never recorded and drops were no-ops. The dock
area now lazily begins the drag in its own capture-phase handler;
drops onto the root edge from the panel's own group split the tree
instead of being swallowed as self-drops.
- MenuBar: hover another title with a menu open to switch (scrubbing)
- menu popup width computed from the longest label; ROW_HEIGHT 22
- dock tab bar 26px / smaller tab text; viewer transport tightened
- menu: add runtime set-checked path (MenuItem::set_checked/clear_checked,
Menu::set_item_checked recursive, MenuBar::set_item_checked)
- dock: Split now stores per-child ratios (sum 1.0) so 3+ panels on one
axis keep distinct sizes; resize_split_child adjusts a single boundary,
resize_split keeps its two-arg whole-share semantics; one handle per
boundary; DockLayoutState VERSION bumped to 2 for the new ratios field
- audio_meter: MeterOrientation::Vertical for the 26px transport strip,
segments lit bottom to top
- viewer: ViewerFrameSource::CpuFrame + set_cpu_frame (BGRA8 RenderImage
via the sprite atlas) for platforms without CVPixelBuffer
- timeline: TimeDisplay::TimecodeDropFrame (SMPTE drop-frame for NTSC
rates, non-drop fallback otherwise)
- gpui_widgets: regression test pinning the fractional spacing helpers
(py_0p5/py_1p5/py_2p5/py_3p5 already exist; no _0_5 aliases added)