Design View: drop the undo blocks around writes that mint nothing; the membership actions own theirs

Flag writes are silent from a timer, so a block around a reapply or the reconcile
repair could only manufacture a point. The real switch's span is unchanged.
This commit is contained in:
2026-08-07 14:41:17 -04:00
parent 67d9ec3da9
commit 39529a5ac4
8 changed files with 141 additions and 144 deletions
+7 -19
View File
@@ -1,9 +1,9 @@
#pragma once
// REAPER-facing shell of Design View: reads the live folder tree, runs
// ViewModeModel's pure planner, and applies the resulting flag / lane / parent
// writes under ONE undo block. See src/shell/view/CLAUDE.md for the enforced
// invariants (never touch master/mute, solo cached per mode and never lost,
// record-based restore).
// writes — under ONE undo block on a real switch, under none at all on a reapply.
// See src/shell/view/CLAUDE.md for the enforced invariants (never touch
// master/mute, solo cached per mode and never lost, record-based restore).
#include <string>
@@ -22,20 +22,6 @@ namespace reasampler {
// `nullptr` meaning the current project here is inferred by analogy, not confirmed.
bool transportBlocksModeSwitch(ReaProject* proj);
// Does one applyMode leave an undo point behind?
//
// A REAPPLY that wrote nothing must not: the load-tick reapply over a project saved
// fully parked re-plans a park for every inactive leaf and finds every flag already
// where it wants them, so a point there would mean opening a project costs an undo
// step. `Undo_EndBlock2(proj, "", 0)` is the discard form (mintManagedLanes' no-op
// path and the reconcile pass use the same idiom).
//
// A real switch mints regardless, fail-safe: it is an explicitly fired action and has
// to stay undoable even in the degenerate case where the plan found nothing to write.
inline bool applyMintsUndoPoint(bool realSwitch, bool wroteAnything) {
return realSwitch || wroteAnything;
}
// True while an applyMode call is on the stack. applyMode fails closed when
// re-entered, and this lets a caller with no fallback test BEFORE it spends a
// one-shot signal on a call that would be refused — see main.cpp's load glue.
@@ -45,7 +31,8 @@ bool modeApplyInProgress();
// the outgoing mode's solo state and replays the incoming mode's, runs planToggle,
// applies the park/restore flag writes plus managed-lane and parent-visibility
// writes, then sets the active mode. ONE switch is ONE undo point; everything it
// moved rolls back in a single Ctrl-Z.
// moved rolls back in a single Ctrl-Z. A REAPPLY leaves no point at all — it opens no
// block, because none of what it writes mints one on its own.
//
// FX are NOT written here. Offlining a parked chain is the reclaimer's job, off this
// path: TrackFX_SetOffline was 1897ms of a measured 1942ms switch, against 0.02ms for
@@ -53,7 +40,8 @@ bool modeApplyInProgress();
//
// A REAL switch therefore RETURNS WITH ITS UNDO BLOCK STILL OPEN (fx_reclaim's
// UndoSpan): the reclaimer closes it once the parking has drained, which is what keeps
// the switch and its FX writes ONE point rather than two. A reapply closes its own.
// the switch and its FX writes ONE point rather than two. A reapply opens none, so a
// caller that wants its own act undoable opens its own (design_view_actions does).
//
// Returns false (no mutation) if `targetModeId` isn't registered, if this is a real
// switch (target != active) while the transport is running, if it is re-entered