Fix drag-out losing audio and FX-container drops losing the capture; re-home ingest under shell/actions

This commit is contained in:
2026-07-29 23:49:53 -04:00
parent a689fb75eb
commit 0800760833
16 changed files with 269 additions and 45 deletions
+27 -10
View File
@@ -298,8 +298,13 @@ void onMouseMove(int x, int y) {
if (gesture == DragGesture::OsDrag) {
// Resolve the payload to existing on-disk paths BEFORE tearing down internal
// drag state (the resolver reads dragSourceBankId / dragSampleIds).
// drag state (the resolver reads dragSourceBankId / dragSampleIds), then let the
// pure rule couple the two side effects: an unresolvable payload must leave the
// internal drag intact rather than wind it down for a hand-off that never runs —
// a half-torn-down drag reads to the user as "the drag did nothing, try again".
const std::vector<std::string> paths = resolveDragPathsForOs();
const ui::OsHandoff handoff = ui::decideOsHandoff(paths);
if (!handoff.releaseInternalDrag) return;
// DoDragDrop runs its own modal loop and takes over mouse capture, so the internal
// drag must be fully wound down first.
@@ -313,8 +318,7 @@ void onMouseMove(int x, int y) {
g_panel.dragPrimaryId.clear();
invalidatePanel();
// Empty path list -> nothing draggable (all stale/missing); do not start a drag.
if (!paths.empty())
if (handoff.startOsDrag)
initiateDragOut(g_panel.hwnd, paths); // COPY-ONLY; blocking on Windows
return;
}
@@ -377,14 +381,27 @@ void resetDragState() {
// OsDragOut is never seen here: the pointer-left-client handoff happens live in onMouseMove.
void onLBtnUp(int x, int y) {
if (g_panel.dragging) {
// Drop-and-load: a release while hover-tracking a valid FX hotspot instantiates a
// ReaSampler 9000 on that track preloaded with the dragged capture — NOT a bank move,
// NOT an OS drag, NEVER a timeline insert. Takes priority over the in-grid / cross-bank
// drop. Single-capture only, so dragSampleIds.front() is the capture.
if (g_panel.instrumentDropTrack && g_panel.dragSampleIds.size() == 1) {
// Drop-and-load: a release over a valid FX hotspot instantiates a ReaSampler 9000 on
// that track preloaded with the dragged capture — NOT a bank move, NOT an OS drag,
// NEVER a timeline insert. Takes priority over the in-grid / cross-bank drop.
// Single-capture only, so dragSampleIds.front() is the capture.
//
// Re-resolve at the RELEASE point rather than trusting only the hover-tracked target:
// WM_MOUSEMOVE is coalesced, so a fast drag onto a dense surface (an FX chain row, a
// container) can release over a hotspot no processed move ever reported. Strictly
// additive — a release-point miss falls back to the tracked target, so the
// hover-then-release-on-the-FX-button path is untouched.
const bool singleCapture = g_panel.dragSampleIds.size() == 1;
MediaTrack* dropTrack = g_panel.instrumentDropTrack;
if (singleCapture) {
POINT sp{x, y};
ClientToScreen(g_panel.hwnd, &sp);
const FxDropTarget fx = resolveFxDropTarget(sp.x, sp.y);
if (fx.valid()) dropTrack = fx.track;
}
if (dropTrack && singleCapture) {
const std::string sampleId = g_panel.dragSampleIds.front();
performInstrumentDrop(g_panel.instrumentDropTrack,
buildInstrumentDropPreset(sampleId));
performInstrumentDrop(dropTrack, buildInstrumentDropPreset(sampleId));
// Read-only over the bank + arrange: the only mutations are the new FX instance +
// its state (both undoable in performInstrumentDrop).
} else {
+1 -1
View File
@@ -14,7 +14,7 @@
#include "shell/panel/panel_window.h"
#include "shell/panel/draw_kit.h"
#include "ingest.h"
#include "shell/actions/ingest.h"
#ifdef _WIN32
#include <windowsx.h> // GET_X_LPARAM / GET_Y_LPARAM (SWELL supplies them on mac/linux)