#pragma once // window_origin — whose code implements a window, and whether the window chain under the pointer // is a plugin's own editor rather than REAPER's chrome. The shell reads the facts (owning process, // the module holding the window CLASS's procedure); this module decides, so the rule is provable // without a DAW. Evidence feeding ui::DropContext::pointerOverPluginEditor. #include #include namespace reasampler::ui { enum class WindowCode { Host, // the host executable itself — REAPER's own chrome and containers System, // an OS module (standard controls, dialog class): says nothing about who placed it Plugin, // any other code — a plugin binary, or a window of another process (bridged plugin) Instrument, // our own ReaSampler 9000 module: FX chrome, not a hand-off-worthy plugin editor Unknown, // the procedure resolved to no loaded module — no evidence either way }; // What the shell observed about ONE window. The CLASS procedure, not the instance one, because an // extension subclassing a REAPER window swaps only the instance procedure — reading that would // make REAPER's own chrome look like foreign code. struct WindowFacts { bool otherProcess = false; // the window belongs to a process other than the host's bool procResolved = false; // the class procedure lies inside a loaded module bool hostModule = false; // ...and that module is the host executable // ...and that module is THIS channel's ReaSampler 9000 .vst3 (basename match, set by the // shell against app_version::vstOutputName() + ".vst3" — stable and beta each recognise only // their own binary, never the other channel's). A drag over our own instrument's editor is // the load-bearing-principle instrument-drop outcome, not the OS hand-off other plugins get. bool ownModule = false; std::string modulePath; // that module's file path, UTF-8 }; // `systemRoot` is the OS directory (GetSystemWindowsDirectory); a module beneath it is System. // An empty root makes every non-host module Unknown rather than Plugin: without it a standard // button in REAPER's chrome would be indistinguishable from plugin code. WindowCode classifyWindowCode(const WindowFacts& facts, const std::string& systemRoot); // `chain` runs from the window under the pointer up to and including its top-level root. True iff // any window in it is Plugin code: a plugin's editor sits beneath REAPER's container, and a // standard control INSIDE that editor is still under the plugin's own window. Unknown is never // proof — the hand-off this gates is modal, so it needs positive evidence. bool isPluginEditorChain(const std::vector& chain); } // namespace reasampler::ui