Fix drag-handoff bugs: gate FX re-resolve on outside-panel, cache unresolvable OS-drag verdict, block double FX-add retry
This commit is contained in:
@@ -64,10 +64,11 @@ HGLOBAL buildHDrop(const std::vector<std::string>& paths) {
|
||||
|
||||
// COM reference counts MUST be interlocked. A CF_HDROP target is free to marshal the data
|
||||
// object into another apartment and finish the copy on a background thread AFTER DoDragDrop
|
||||
// has returned (Explorer's async file copy does exactly this). A plain ++/-- there races the
|
||||
// source thread's post-DoDragDrop Release: one lost increment destroys the object — and with
|
||||
// it the source HGLOBAL — before the target reads it, and the drop lands with no file. That
|
||||
// race is intermittent and a retry usually wins it; do not "simplify" these back.
|
||||
// has returned; Explorer's async file copy is suspected to do exactly this, though that
|
||||
// specific behavior is not confirmed by experiment. A plain ++/-- there races the source
|
||||
// thread's post-DoDragDrop Release: one lost increment destroys the object — and with it the
|
||||
// source HGLOBAL — before the target reads it, and the drop lands with no file. That race is
|
||||
// intermittent and a retry usually wins it; do not "simplify" these back.
|
||||
inline ULONG comAddRef(volatile LONG& refs) {
|
||||
return static_cast<ULONG>(InterlockedIncrement(&refs));
|
||||
}
|
||||
@@ -234,6 +235,15 @@ bool initiateDragOut(HWND__* /*panelHwnd*/, const std::vector<std::string>& abso
|
||||
return hr == DRAGDROP_S_DROP && effect == DROPEFFECT_COPY;
|
||||
}
|
||||
|
||||
bool canInitiateDragOut(const std::vector<std::string>& absolutePaths) {
|
||||
if (absolutePaths.empty()) return false;
|
||||
if (!ensureOleForThisThread()) return false;
|
||||
HGLOBAL hdrop = buildHDrop(absolutePaths);
|
||||
if (!hdrop) return false;
|
||||
GlobalFree(hdrop); // probe only — initiateDragOut builds its own on the real attempt
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace reasampler
|
||||
|
||||
#else // ---- macOS / Linux (SWELL) -----------------------------------------------------
|
||||
@@ -260,6 +270,13 @@ bool initiateDragOut(HWND__* panelHwnd, const std::vector<std::string>& absolute
|
||||
return true; // fire-and-forget; SWELL owns the drag from here (no accept/cancel return)
|
||||
}
|
||||
|
||||
// SWELL exposes no readiness probe ahead of SWELL_InitiateDragDropOfFileList (which itself
|
||||
// reports no accept/cancel outcome) — the non-empty check is the only thing knowable in
|
||||
// advance on this platform.
|
||||
bool canInitiateDragOut(const std::vector<std::string>& absolutePaths) {
|
||||
return !absolutePaths.empty();
|
||||
}
|
||||
|
||||
} // namespace reasampler
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user