Hand a card dragged onto a plugin's own editor to the OS as a file drop; withdraw the OLE drag when the pointer returns to REAPER
A code-ownership proof (window class procedure's module, via the pure window_origin) plus REAPER's FX-surface token routes a plugin editor to OLE; FX chrome keeps the instrument drop. The OLE loop re-asks the law each turn, so passing a plugin editor stays reversible.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
// window_origin — pure implementation. See window_origin.h.
|
||||
|
||||
#include "core/ui/window_origin.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace reasampler::ui {
|
||||
|
||||
namespace {
|
||||
|
||||
// Case-folded (ASCII only — Windows' own directory names are ASCII), separator-unified, with the
|
||||
// "\\?\" long-path prefix GetModuleFileName may report dropped, so the same directory compares
|
||||
// equal however each API chose to spell it.
|
||||
std::string normalizePath(const std::string& p) {
|
||||
std::string s = p.rfind("\\\\?\\", 0) == 0 ? p.substr(4) : p;
|
||||
for (char& c : s) {
|
||||
if (c == '/') c = '\\';
|
||||
else if (c >= 'A' && c <= 'Z') c = static_cast<char>(c - 'A' + 'a');
|
||||
}
|
||||
while (!s.empty() && s.back() == '\\') s.pop_back();
|
||||
return s;
|
||||
}
|
||||
|
||||
// Directory containment, not string prefix: C:\Windows must not claim C:\WindowsApps.
|
||||
bool isBeneath(const std::string& path, const std::string& dir) {
|
||||
const std::string p = normalizePath(path);
|
||||
const std::string d = normalizePath(dir);
|
||||
return !d.empty() && p.size() > d.size() && p.compare(0, d.size(), d) == 0 &&
|
||||
p[d.size()] == '\\';
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WindowCode classifyWindowCode(const WindowFacts& facts, const std::string& systemRoot) {
|
||||
// Another process's procedure address means nothing in ours; the process boundary is itself
|
||||
// the proof. Inside an FX window that is the bridged plugin's editor.
|
||||
if (facts.otherProcess) return WindowCode::Plugin;
|
||||
if (!facts.procResolved) return WindowCode::Unknown;
|
||||
if (facts.hostModule) return WindowCode::Host;
|
||||
if (normalizePath(systemRoot).empty()) return WindowCode::Unknown;
|
||||
return isBeneath(facts.modulePath, systemRoot) ? WindowCode::System : WindowCode::Plugin;
|
||||
}
|
||||
|
||||
bool isPluginEditorChain(const std::vector<WindowCode>& chain) {
|
||||
return std::find(chain.begin(), chain.end(), WindowCode::Plugin) != chain.end();
|
||||
}
|
||||
|
||||
} // namespace reasampler::ui
|
||||
Reference in New Issue
Block a user