Ψ-W1-T2 review remediation: solo restore drops on visible-in-target, not parked; N-mode segments read dead when unroutable
Fixes a hidden-parent solo replay that could silence the mix. Also closes the N-mode segment silent no-op, amends the invariant comment, trims view.cpp under 600 lines, hedges two SDK inferences, drops a dead null-check.
This commit is contained in:
@@ -44,6 +44,20 @@ TailSetting currentTail() {
|
||||
return g_panel.session ? g_panel.session->tail() : TailSetting{};
|
||||
}
|
||||
|
||||
// The registered activate action behind a footer mode segment, or 0 if the mode has none.
|
||||
// Routing the segment through the SAME action the Actions list fires is what gives a
|
||||
// panel-initiated switch the persist + repaint it used to skip; a mode with no such
|
||||
// action (the model is N-mode, the UI ships two) resolves to 0 here, which
|
||||
// modeSegmentEnabled reads as unroutable so the segment paints dead rather than live-
|
||||
// but-inert. Non-anonymous: panel_render.cpp resolves the same id to compute that bool.
|
||||
int modeActivateCommandId(const std::string& modeId) {
|
||||
ActionBarRow row{};
|
||||
if (modeId == kArrangeModeId) row.suffix = "VIEW_ACTIVATE_ARRANGE";
|
||||
else if (modeId == kDesignModeId) row.suffix = "VIEW_ACTIVATE_DESIGN";
|
||||
else return 0;
|
||||
return resolveBarCommandId(row);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Commits the current tail setting to ext state and marks the active project dirty so the
|
||||
@@ -76,18 +90,6 @@ bool handleToolbarClick(int x, int y, const ActionBarRect& bar,
|
||||
return true;
|
||||
}
|
||||
|
||||
// The registered activate action behind a footer mode segment. Routing the segment
|
||||
// through the SAME action the Actions list fires is what gives a panel-initiated switch
|
||||
// the persist + repaint it used to skip; a mode with no such action (the model is
|
||||
// N-mode, the UI ships two) is unreachable from the footer rather than routed around it.
|
||||
int modeActivateCommandId(const std::string& modeId) {
|
||||
ActionBarRow row{};
|
||||
if (modeId == kArrangeModeId) row.suffix = "VIEW_ACTIVATE_ARRANGE";
|
||||
else if (modeId == kDesignModeId) row.suffix = "VIEW_ACTIVATE_DESIGN";
|
||||
else return 0;
|
||||
return resolveBarCommandId(row);
|
||||
}
|
||||
|
||||
// True iff `tr` has I_FREEMODE==2 (fixed lanes enabled). Value verified in view.cpp;
|
||||
// reproduced locally so this file stays self-contained.
|
||||
constexpr int kFreeModeFixedLanes = 2;
|
||||
@@ -316,11 +318,10 @@ void handleClick(int x, int y) {
|
||||
if (seg < static_cast<int>(modes.size())) {
|
||||
const std::string& id = modes[static_cast<std::size_t>(seg)].id;
|
||||
const bool isActive = id == view.activeModeId();
|
||||
// Disabled while the transport runs: claimed but inert, the same shape a
|
||||
// disabled toolbar row takes — a dead segment reads inert, never absent,
|
||||
// and never falls through to the grid.
|
||||
if (modeSegmentEnabled(isActive, g_panel.modeSwitchBlocked)) {
|
||||
const int cmd = modeActivateCommandId(id);
|
||||
const int cmd = modeActivateCommandId(id);
|
||||
// Disabled/dead rationale: core/ui/footer_bar.h. Claimed but inert, the
|
||||
// same shape a disabled toolbar row takes — never falls through to the grid.
|
||||
if (modeSegmentEnabled(isActive, g_panel.modeSwitchBlocked, cmd != 0)) {
|
||||
if (cmd != 0 && Main_OnCommand) Main_OnCommand(cmd, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,9 +112,9 @@ void drawFooter(LICE_IBitmap* bmp, int w, int h) {
|
||||
const SegmentRect& s = segs[static_cast<std::size_t>(i)];
|
||||
const Mode& mode = modes[static_cast<std::size_t>(i)];
|
||||
const bool active = mode.id == activeId;
|
||||
// A switch is refused while the transport runs, so an unreachable segment
|
||||
// draws dead rather than inviting a click that would silently do nothing.
|
||||
const bool live = modeSegmentEnabled(active, g_panel.modeSwitchBlocked);
|
||||
// Disabled/dead rationale: core/ui/footer_bar.h.
|
||||
const bool live = modeSegmentEnabled(active, g_panel.modeSwitchBlocked,
|
||||
modeActivateCommandId(mode.id) != 0);
|
||||
const InteractionState state =
|
||||
active ? InteractionState::Active
|
||||
: (live ? hoverState(g_panel.hovered, HoverKind::ModeSegment, i)
|
||||
|
||||
@@ -292,10 +292,10 @@ struct PanelState {
|
||||
unsigned int hoverSinceTick = 0;
|
||||
bool tooltipShown = false;
|
||||
|
||||
// Polled on the OnTimer tick (REAPER exposes no transport-change callback): a mode
|
||||
// switch is refused while the transport runs, so the footer's [Arrange|Design]
|
||||
// segments paint disabled. Cached rather than read per paint AND per click so the
|
||||
// pixel the user saw and the click they made cannot disagree within a tick.
|
||||
// Polled on the OnTimer tick (REAPER exposes no transport-change callback). Feeds
|
||||
// modeSegmentEnabled (core/ui/footer_bar.h). Cached rather than read per paint AND
|
||||
// per click so the pixel the user saw and the click they made cannot disagree
|
||||
// within a tick.
|
||||
bool modeSwitchBlocked = false;
|
||||
|
||||
BankPanelFullHeight fullHeight = BankPanelFullHeight::Split;
|
||||
@@ -485,6 +485,9 @@ void startAudition(int idx);
|
||||
// panel_input.cpp — click/wheel/key routing, accelerator, new-content detection,
|
||||
// and the session-tail read/mutate helpers.
|
||||
TailSetting currentTail();
|
||||
// The registered activate action behind a footer mode segment, or 0 if unroutable.
|
||||
// Shared with panel_render.cpp so paint and click resolve the same id.
|
||||
int modeActivateCommandId(const std::string& modeId);
|
||||
void handleClick(int x, int y);
|
||||
bool handleWheel(int x, int y, int delta);
|
||||
void registerAccel();
|
||||
|
||||
Reference in New Issue
Block a user