From beaec8642a11d692cd204fe0d649632cbd203aee Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Thu, 23 Jul 2026 19:19:10 -0400 Subject: [PATCH] fix: tail toggle/scroll now commits to ext-state immediately markTailDirty() called MarkProjectDirty() but never called saveToActiveProject(), so the new tail value was never written to SetProjExtState. On unsaved projects saveToActiveProject() no-ops cleanly, resolving the companion Major at the same time. --- src/bank_panel.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/bank_panel.cpp b/src/bank_panel.cpp index d8f8688..6f91d69 100644 --- a/src/bank_panel.cpp +++ b/src/bank_panel.cpp @@ -534,11 +534,15 @@ bool pointInFooter(int x, int y) { return f.top < f.bottom && x >= f.left && x < f.right && y >= f.top && y < f.bottom; } -// Marks the active project dirty so a tail-setting change saves with the project. -// A bare tail toggle dirtying the project is intended (it IS project state now). -// persist writes the setting into ext state on the next save; this only flags that a -// save is owed. NON-DESTRUCTIVE: touches nothing in the bank/arrange. +// Commits the current tail setting to ext state and marks the active project dirty +// so the change travels inside the .rpp on Ctrl+S. saveToActiveProject() is the only +// path that calls SetProjExtState for the tail key — calling it here closes the gap +// where toggle/scroll would dirty the project but the new value was never written. +// On an unsaved project saveToActiveProject() no-ops cleanly (documented in persist.h). +// MarkProjectDirty runs unconditionally so REAPER knows a save is owed either way. +// NON-DESTRUCTIVE: touches nothing in the bank/arrange. void markTailDirty() { + if (g_panel.session) g_panel.session->saveToActiveProject(); ReaProject* proj = EnumProjects(-1, nullptr, 0); if (proj) MarkProjectDirty(proj); }