Repository navigation
fix(runtime): preserve frame delivery and add the optional Obsidian theme - #146
Merged
Merged
Conversation
Calendar selection lost the last days of months that require six weeks. Flattening multiple months into five-row chunks also assigned later rows to the wrong month. Generate complete Sunday-first weeks, then render each month as its own column while preserving the existing five-row minimum. Keep the Longbridge calendar lifecycle and record this intentional Mirror to TrackedFork correction in the existing component migration ledger. Move the existing tests to sibling modules and add real rendered selection coverage for August 30/31 beside September in both Dark and Light themes. Validation: all 624 component tests, gallery/font and component API/mirror guardrails pass. The new grid coverage fails when five fixed rows return.
…ls settle A notification from prepaint or paint could leave dirty views queued while the common frame-entry predicate reported a clean window. A separate layout model also lost its observer notification, so waking a frame alone could not invalidate the cached view that consumed the measurement. Treat queued views as draw debt everywhere and publish model notifications through the existing deferred effect queue in every draw phase. This makes previously hidden no-op notification loops observable; remove Input's paint-time notify and make scroll, placeholder, loading, list search mode, and resizable measured geometry notify only when their visible state changes. No additional timer or parallel scheduling state is introduced. Validation: mid-prepaint/paint and cached-model regressions pass; real Input and Resizable forms settle after edits in Dark and Light. Native Windows FireTest applies text/width without a rescue event, then observes two quiet native callbacks with zero renders. Restoring the old dirty predicate or Input paint notification independently makes that native probe fail.
…s it Window cleared needs_present even when the backend skipped a recovering, occluded, or unavailable surface. Without further input the valid scene could then remain unpresented. Return acceptance from PlatformWindow::draw and keep that existing debt armed until the native frame clock succeeds. Carry the contract through DirectX, Metal, X11, Wayland, Web and the test platform. Do not prepare canvas text while a window is unpresentable; the restored frame prepares it once presentation becomes possible. Record input latency only after an accepted present. Validation: real frame-callback tests cover deferred draws, wake requests, hidden canvas text and recovery without rescue input; the full 220-test runtime suite and integration test pass. Windows FireTest covers native clocks and recovery, and Hel1 covers X11/Wayland software surfaces. Metal and Web have source parity here; native Metal validation remains a separate platform check and is not claimed by the Windows run.
A canvas can mark its CPU bake clean after recording GPU commands. When a later scene batch overflowed the instance buffer, dropping that encoder lost the bake permanently: the larger retry saw clean CPU state and never rebuilt the texture. Submit the already recorded commands before retrying. The retry still clears the partial surface and only the final scene presents. Apply the same ordering to wgpu and Metal, including CPU-to-GPU instance buffer synchronization on non-unified Metal memory. DirectX submits its immediate-context work already and needs no corresponding change. Validation: an explicit native-surface regression forces an actual buffer growth after a one-shot retained bake, then reads the final GPU pixel. Hel1 produced the expected RGBA value; restoring encoder discard makes that test fail. Metal has source parity; its native probe is still separate.
The fallback timer called frame(), which registered a new wl_surface frame callback every tick. These requests remain pending until the compositor answers, so a hidden or stalled surface accumulated callbacks indefinitely. Keep one compositor chain: first configure starts it and each completed callback replaces itself. Timer polls only drive GPUI and canvas decisions, preserving the fallback wake that lets Skip become Present without input. No new callback counter or parallel timer is introduced. Validation: Linux build and full functional FireTest stages ran on the Hel1 Weston session, including idle and device recovery. Software-renderer CPU limits and intermittent diagnostic-client disconnects remain reported separately; this commit does not claim to fix either unrelated observation.
Synchronous X11 setup can consume socket data into the client event buffer. Calloop then sees no readable socket, so a newly mapped window can stay blank until unrelated input. Schedule one idle drain after GPUI installs the window callbacks and explicitly wake calloop so that drain runs. This uses the existing event processor, not another polling loop. Hel1 mutation qualification reproduced a blank startup and missing chart probe when this block was removed; restoring it delivered the initial frame and passed the functional X11 FireTest stages without rescue input.
…oint FireTest needs to distinguish an unchanged view that really rebuilt from a notification or reuse of its cached scene. Add opt-in per-App counting where the concrete Render implementation is invoked, so application code does not need a manually maintained list of instrumented panels. The default path performs only an Option check: no clock, allocation, hash or synchronization. Sampling drains the interval; disabling drops it so old samples cannot leak across diagnostic runs. Independent apps do not share the counters. Validation: runtime regressions distinguish cached child reuse from parent renders and cover enable, repeated enable, drain, disable and re-enable. The terminal native idle and form probes consume these actual counts.
Keep the borrowed raw callback API: it intentionally lets the terminal render inside MoonUI's native pass without another abstraction or copy. Document its real safety boundary instead. These are pointers to Rust objects, not a stable C ABI, so producer and consumer must resolve the same wgpu Cargo package source and version. The companion terminal change replaces its separate git-sourced wgpu with the registry package already used by MoonUI. Matching version text alone would not make two distinct Cargo package identities interchangeable.
Later draw submissions can replace a useful shader validation diagnostic with a generic invalid-pipeline error. Keep the first uncaptured error until the existing consumer drains it, retaining the actual failure cause without adding a separate error queue or changing recovery behavior. This was exercised while diagnosing the terminal's Linux candle shader; the original validation reason now survives the later invalid submissions.
FireTest must prove that retained charts return after their GPU resources are destroyed, without depending on a driver crash or a system-wide TDR. Expose a diagnostic request through Window and PlatformWindow. Windows uses its existing VSync device owner; X11 and Wayland destroy the shared wgpu device and let the ordinary native draw path recover it. Refresh all windows sharing the device. Unsupported platforms explicitly return false. Preserve the existing adapter policy during recovery: a session already using a CPU adapter can recreate that class, while a hardware session still refuses a silent fallback to software. This makes recovery testable on the Hel1 software lab without weakening hardware-session behavior. Validation: the terminal FireTest performs two controlled losses with no new market data, checks retained history and generations on Windows and Linux, and reads exact restored own-pass image layers on DirectX. This is not a driver-hang/TDR or a native Metal recovery test.
The app-global set of open deferred popovers disabled every Input context menu whenever any popover was open. The renderer already supports nested deferred overlays, so that guard was both obsolete and broader than the window or control it was meant to protect. Remove the guard and its registry, including Select/Combobox/Popover writes. Visibility remains with each existing owner; Root keeps overlay placement and dismissal. No replacement global state or native popup window is added. Validation: real right-click events reach the Input menu inside a popover and in another window, and the nested Root menu survives actual prepaint with non-empty bounds in both Dark and Light themes. The full component suite and final guardrails pass with the companion focus changes.
A row callback could open a modal while the menu still owned focus. The later menu close then either stole the modal's focus or left its return target on a removed menu. Route selection through the actual PopoverState and dismiss it before invoking the row action or selection callback. Popover close snapshots its descendant/tracked focus before content leaves the dispatch tree. Deferred restoration runs only while that exact focus is still owned; it never steals focus already transferred elsewhere. This removes the duplicate dropdown close plan and parallel open-state updates rather than adding another focus-restoration mechanism. Validation: real Root dialog/menu flows in Dark and Light cover opening a modal, a menu inside that modal, return to the original trigger, tracked and descendant focus, no previous focus, and deliberate transfer elsewhere. Existing selection behavior tests remain; removed policy-only assertions are replaced by lifecycle tests that fail when close ordering is reversed.
Update the existing fork reasons and byte/hash ledger for the component fixes in this series: convergent Input/List/Resizable invalidation and local popover ownership supporting nested input menus. Keep the original donor references and audit baseline; do not broaden drift budgets or conceal unrelated upstream differences. The calendar class migration is recorded with its own behavior commit. These records describe the final component source already covered by the runtime and component regressions, so future donor updates can distinguish intentional fixes from accidental drift. Full component API, mirror and audit guardrails pass against this exact snapshot.
MoonInput Custom metrics supplied a height, but the shared Input applied it only in multiline mode. A 19px field became 22px with the terminal font delta, breaking the wrapper geometry contract. Apply the existing optional height after the multiline auto-height choice. Preserve default sizing and update only the Input/TextArea donor-drift baseline. Regression: measure unconstrained real GPUI layout for Compact, Small, Normal, Custom and minimum-height clamping in Dark and Light. The old code fails at 22px versus 19px; the fix passes on Windows and Linux. MoonUI guardrails and terminal workspace checks pass.
MoonTextArea::size accepted MoonTextAreaSize from a private module, so downstream users could not name the supported variants. Re-export the existing enum through the Moon facade and record the exact public signature. No new wrapper or sizing behavior is introduced. Validated with MoonUI component/gallery/API guardrails and the full terminal workspace.
The Linux MoonWindowFrame close button removed its window directly, bypassing the native should-close callback. Applications could neither veto that close nor distinguish it from owner teardown. Retain one replaceable policy on Window and expose request_close for client-drawn controls. Native close uses the same policy; remove_window remains an unconditional teardown operation. Preserve the existing callback registration API and release its borrow before invoking user code. Real GPUI test windows verify veto, callback replacement, accepted/default close, forced removal and the FrameButton path on Windows and Linux. Native compositor click/lifecycle qualification remains separate; no macOS or Linux visual proof is claimed by these tests.
A downstream retained chart must exercise prepare_text inside the real window frame callback to detect an already-served frame being requested again. Expose the existing test-window callback through VisualTestContext and the test-support feature instead of constructing an artificial public text context. Production behavior is unchanged. Validated by the terminal readout RED/GREEN regression and the full MoonUI runtime/component suites.
Closing a side root stopped rendering its subtree but left its selected panel active. That hidden subtree could no longer deliver its own deactivation. This is a library API defect; MoonTerminal currently does not call these public side-toggle methods. Pass Window through set_dock_open and toggle_dock so the existing Panel lifecycle can run at the visibility transition. Synchronize only the changed side subtree and preserve its selected-tab runtime. A currently valid zoom keeps sole visibility and receives no activity callbacks when an unrelated side flag changes. No new activity registry, timer or retained state is introduced. API change: both methods now require the host Window, matching the lifecycle operations they perform. Update their two recorded public signatures; no in-repository production caller requires migration. Validation: a real GPUI window/probe regression fails with the old active panel after close. An independently reviewed broader-sync variant also fails with four extra zoom callbacks. The final implementation passes close/reopen, no-op, selected-index and zoom-preservation checks. MoonUI full guardrails pass (647 component tests, 12 gallery tests); terminal workspace Clippy passes. Astra reviewed the final correction.
Add a selectable dark Obsidian palette and a palette-driven Facet skin for Moon components. Keep existing Flat themes, their default values, layout geometry, interaction owners and persistence identity unchanged. Adapt the existing button/input/select/progress/dock engines instead of duplicating their lifecycle. Preserve colored dropdown variants and use one donor Progress animation engine with track/fill paint hooks. Keep snapshot theme identity distinct from dark/light mode, so Obsidian cannot overwrite Dark captures. Preserve the custom single-line input-height fix and its existing regression when integrating the author's tests. Validation: 732 component tests, 13 gallery tests, bundled fonts, formatting and component audit/API/donor mirror checks pass. Nineteen of twenty native Dark/Light pages match pre-integration PNGs byte-for-byte; the remaining difference is one hovered segment. Ten Obsidian pages and native Obsidian -> Light -> Dark switching were inspected. Historical repository PNGs predate the current gallery and were not rewritten to hide their mismatch. Independent Sol/Astra reviews completed.
guyverino
added a commit
to Moonbot-Tech/MoonTerminal
that referenced
this pull request
Nov 6, 2026
Moonbot-Tech/MoonUI#146 is on master, so the review branch reference goes. The lock's MoonUI rows stay stale by design: CI and the release refresh them to master. The only lock change left is dropping the zed wgpu fork.
guyverino
pushed a commit
to Moonbot-Tech/MoonTerminal
that referenced
this pull request
Nov 6, 2026
…saves and Obsidian (#1267) Keep chart geometry off the price and time gutters, replay retained layers after a GPU replacement, present the final throttled book update, move recurring saves to one background writer, preserve unreadable config originals, give status, market and catalog changes their own notifications, pin COIN-M knowledge to each money batch, and add the selectable Obsidian theme. Pairs with Moonbot-Tech/MoonUI#146. Refs #1190.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rendering could lose a requested follow-up frame, discard a pending presentation, or keep unchanged controls requesting work. This series fixes those shared runtime paths and adds the optional Obsidian theme through MoonUI's existing component engines.
The companion MoonTerminal PR #1267 consumes these fixes and adds native regression coverage. Each commit describes one change and its reason; please preserve the semantic commit history when merging this series.
Changes
Validation
Review boundaries