RAM2118 commited on
Commit
8ab499b
·
verified ·
1 Parent(s): 2dc45d7

fix: show plugin GUI in-process (inside Ableton window) not from Helper

Browse files

ROOT CAUSE: Moving GUI to Helper process broke it. macOS treats Helper
as separate app → opens in different Space when fullscreen.

SOLUTION: PluginBridge.vst3 (in-process) loads a GUI-only plugin instance.
This instance doesn't process audio — it's only for displaying the editor.
Ableton manages it as a normal plugin window (same as Pro-Q 4 native).

Parameter sync: GUI instance ↔ Helper via IPC (bidirectional).
- User moves knob on GUI → notify Helper → Helper updates real instance
- MCP/automation changes param on Helper → notify Plugin → update GUI instance

Helper no longer shows any GUI window.

Files changed (1) hide show
  1. Source/Helper/HelperPluginHost.cpp +6 -103
Source/Helper/HelperPluginHost.cpp CHANGED
@@ -4,66 +4,6 @@
4
  #include <pthread.h>
5
  #include <sched.h>
6
 
7
- #if JUCE_MAC
8
- #include <objc/objc.h>
9
- #include <objc/message.h>
10
- #endif
11
-
12
- // Configure window for floating-panel behavior that works in fullscreen
13
- // MUST be called BEFORE the window is made visible
14
- static void configureAsOverlayPanel(juce::Component* window)
15
- {
16
- #if JUCE_MAC
17
- if (auto* peer = window->getPeer())
18
- {
19
- auto* nsWindow = (id)peer->getNativeHandle();
20
-
21
- // --- COLLECTION BEHAVIOR (MUST be set before visible) ---
22
- // canJoinAllSpaces = 1 << 0 (appear on all desktops/spaces)
23
- // fullScreenAuxiliary = 1 << 8 (can appear over fullscreen apps)
24
- // stationary = 1 << 4 (don't move with space switches)
25
- // ignoresCycle = 1 << 6 (skip in Cmd+` cycling)
26
- long behavior = (1 << 0) | (1 << 8) | (1 << 4) | (1 << 6);
27
- ((void(*)(id, SEL, long))objc_msgSend)(nsWindow, sel_registerName("setCollectionBehavior:"), behavior);
28
-
29
- // --- WINDOW LEVEL ---
30
- // Level 25 = NSStatusWindowLevel (above fullscreen apps)
31
- ((void(*)(id, SEL, long))objc_msgSend)(nsWindow, sel_registerName("setLevel:"), 25);
32
-
33
- // Don't hide when the helper app loses focus
34
- ((void(*)(id, SEL, int))objc_msgSend)(nsWindow, sel_registerName("setHidesOnDeactivate:"), 0);
35
- }
36
- #endif
37
- }
38
-
39
- // Make the window appear without stealing focus (call AFTER visible)
40
- static void showWithoutFocusSteal(juce::Component* window)
41
- {
42
- #if JUCE_MAC
43
- if (auto* peer = window->getPeer())
44
- {
45
- auto* nsWindow = (id)peer->getNativeHandle();
46
- ((void(*)(id, SEL))objc_msgSend)(nsWindow, sel_registerName("orderFrontRegardless"));
47
- }
48
- #endif
49
- }
50
-
51
- // Custom window — no native title bar close issues with accessory policy
52
- class PluginGuiWindow : public juce::DocumentWindow
53
- {
54
- public:
55
- PluginGuiWindow(const juce::String& name)
56
- : DocumentWindow(name, juce::Colour(0xff1a1a2e), DocumentWindow::allButtons, true)
57
- {
58
- setUsingNativeTitleBar(true);
59
- }
60
-
61
- void closeButtonPressed() override
62
- {
63
- setVisible(false);
64
- }
65
- };
66
-
67
  HelperPluginHost::HelperPluginHost()
68
  {
69
  #if JUCE_PLUGINHOST_VST3
@@ -77,7 +17,6 @@ HelperPluginHost::HelperPluginHost()
77
  HelperPluginHost::~HelperPluginHost()
78
  {
79
  stopProcessing();
80
- hideGui();
81
  unloadPlugin();
82
  }
83
 
@@ -137,7 +76,6 @@ bool HelperPluginHost::loadPlugin(const juce::String& path, double sampleRate, i
137
 
138
  void HelperPluginHost::unloadPlugin()
139
  {
140
- hideGui();
141
  if (plugin)
142
  {
143
  plugin->releaseResources();
@@ -282,54 +220,19 @@ bool HelperPluginHost::setParams(const std::map<int, float>& values)
282
  }
283
 
284
  // --- GUI ---
 
 
 
285
 
286
  void HelperPluginHost::showGui()
287
  {
288
- if (!plugin || !plugin->hasEditor()) return;
289
-
290
- juce::MessageManager::callAsync([this]()
291
- {
292
- if (!plugin) return;
293
-
294
- // If window exists but hidden, just show it
295
- if (guiWindow)
296
- {
297
- // Re-apply overlay config before showing (in case Space changed)
298
- configureAsOverlayPanel(guiWindow.get());
299
- guiWindow->setVisible(true);
300
- showWithoutFocusSteal(guiWindow.get());
301
- return;
302
- }
303
-
304
- auto* editor = plugin->createEditor();
305
- if (!editor) return;
306
-
307
- guiWindow = std::make_unique<PluginGuiWindow>(plugin->getName());
308
- guiWindow->setContentOwned(editor, true);
309
- guiWindow->setResizable(true, true);
310
- guiWindow->centreWithSize(editor->getWidth(), editor->getHeight());
311
-
312
- // CRITICAL: configure overlay behavior BEFORE making visible
313
- configureAsOverlayPanel(guiWindow.get());
314
-
315
- // NOW make visible
316
- guiWindow->setVisible(true);
317
-
318
- // Show without stealing focus from Ableton
319
- showWithoutFocusSteal(guiWindow.get());
320
- });
321
  }
322
 
323
  void HelperPluginHost::hideGui()
324
  {
325
- if (guiWindow)
326
- {
327
- juce::MessageManager::callAsync([this]()
328
- {
329
- if (guiWindow)
330
- guiWindow->setVisible(false);
331
- });
332
- }
333
  }
334
 
335
  // --- State ---
 
4
  #include <pthread.h>
5
  #include <sched.h>
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  HelperPluginHost::HelperPluginHost()
8
  {
9
  #if JUCE_PLUGINHOST_VST3
 
17
  HelperPluginHost::~HelperPluginHost()
18
  {
19
  stopProcessing();
 
20
  unloadPlugin();
21
  }
22
 
 
76
 
77
  void HelperPluginHost::unloadPlugin()
78
  {
 
79
  if (plugin)
80
  {
81
  plugin->releaseResources();
 
220
  }
221
 
222
  // --- GUI ---
223
+ // GUI is NO LONGER handled by the Helper process.
224
+ // It's now handled in-process by PluginBridgeEditor (inside Ableton).
225
+ // These stubs remain for IPC compatibility but do nothing.
226
 
227
  void HelperPluginHost::showGui()
228
  {
229
+ // No-op — GUI is shown in-process by PluginBridgeEditor
230
+ DBG("HelperPluginHost::showGui() — no-op, GUI is in-process now");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  }
232
 
233
  void HelperPluginHost::hideGui()
234
  {
235
+ // No-op
 
 
 
 
 
 
 
236
  }
237
 
238
  // --- State ---