Design View: no undo block may open over the reclaim span, and a reapply closes none

Every opener ends the span first, so a tag fired mid-drain no longer hijacks the
switch's point. One stated criterion governs both lane sites; no-op actions discard.
This commit is contained in:
2026-08-07 15:13:52 -04:00
parent 39529a5ac4
commit b2f6b3f1d0
9 changed files with 210 additions and 76 deletions
+13 -5
View File
@@ -15,8 +15,8 @@ class ReaProject;
namespace reasampler {
// `freeMode` alone decides whether UpdateTimeline is owed (SDK: required after an
// I_FREEMODE change); `wrote` is any project write at all, which is what the apply's
// undo-point decision reads.
// I_FREEMODE change); `wrote` is a REAPER write, the reading ModeApplyResult
// (view.h) carries through to the caller's undo-point decision.
struct LaneApplyResult {
bool freeMode = false;
bool wrote = false;
@@ -24,14 +24,22 @@ struct LaneApplyResult {
// Reconciles each op's durable laneKey to the track's current ordinal (a
// stale/renamed/deleted key is pruned, never mis-driven) and drives C_LANEPLAYS.
//
// Opens NO undo block, where mintManagedLanes below opens one over the same
// parameters — the one criterion this directory's CLAUDE.md states, applied: this
// re-asserts derived state the view model recomputes from membership on every apply,
// so nothing here needs to survive as a point of its own; minting creates lanes and
// re-homes items, which no re-derivation reproduces.
LaneApplyResult applyLaneOps(const TrackByGuid& handleByGuid,
const std::vector<LanePlayOp>& lanes);
// Splits any track visible in more than one mode while carrying its own media into
// fixed lanes (one managed lane per involved mode), assigns items, and records
// ownership in `model`. Wraps the mutation in one Undo block when non-empty. Returns
// true if any lane was minted (repaint hint). `proj` == nullptr means the current
// project.
// ownership in `model`. Wraps the mutation in one Undo block when non-empty — see
// applyLaneOps above for why this site opens one and that one does not — and ENDS THE
// RECLAIM SPAN first, since REAPER's blocks are a depth counter and this is reachable
// from a timer tick with a prior switch's span still open. Returns true if any lane
// was minted (repaint hint). `proj` == nullptr means the current project.
bool mintManagedLanes(ViewModeModel& model, ReaProject* proj);
// Recovers managed-lane ownership from durable P_LANENAME on project open —