diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index 123a51eade..e3949b70bb 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -42,8 +42,6 @@ namespace juce #if JUCE_LINUX || JUCE_BSD -using EventProcPtr = void (*)(XEvent*); - static Window getChildWindow (Window windowToCheck) { Window rootWindow, parentWindow; @@ -106,6 +104,8 @@ public: #if JUCE_WINDOWS addAndMakeVisible (embeddedComponent); + #elif JUCE_LINUX || JUCE_BSD + addAndMakeVisible (xembedComponent); #endif } @@ -182,23 +182,7 @@ public: void paint (Graphics& g) override { - #if JUCE_LINUX || JUCE_BSD - if (isOpen) - { - if (pluginWindow != 0) - { - auto clip = componentToVstRect (*this, g.getClipBounds().toNearestInt()); - - X11Symbols::getInstance()->xClearArea (display, pluginWindow, clip.getX(), clip.getY(), - static_cast (clip.getWidth()), - static_cast (clip.getHeight()), True); - } - } - else - #endif - { - g.fillAll (Colours::black); - } + g.fillAll (Colours::black); } void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) override @@ -213,17 +197,11 @@ public: #if JUCE_WINDOWS embeddedComponent.setBounds (getLocalBounds()); #elif JUCE_LINUX || JUCE_BSD - const auto pos = componentToVstRect (*this, getLocalBounds()); + xembedComponent.setBounds (getLocalBounds()); if (pluginWindow != 0) { auto* symbols = X11Symbols::getInstance(); - symbols->xMoveResizeWindow (display, - pluginWindow, - pos.getX(), - pos.getY(), - (unsigned int) pos.getWidth(), - (unsigned int) pos.getHeight()); symbols->xMapRaised (display, pluginWindow); symbols->xFlush (display); } @@ -431,6 +409,8 @@ private: #if JUCE_WINDOWS auto* handle = embeddedComponent.getHWND(); + #elif JUCE_LINUX || JUCE_BSD + auto* handle = desktopComponent.getPeer()->getNativeHandle(); #else auto* handle = getWindowHandle(); #endif @@ -722,8 +702,33 @@ private: void* originalWndProc = {}; int sizeCheckCount = 0; #elif JUCE_LINUX || JUCE_BSD + // This is to provide a consistent X11 window handle with the same lifetime as the + // VSTPluginWindow. Using the VSTPluginWindow's peer directly would mean that the X11 window + // handle could change if the same VST window instance is repeatedly added/removed from the + // desktop. + // We then XEmbed this stable window into the VSTPluginFormat, and also use the stable window + // as the parent for the client VST window. + // We're not XEmbedding the client VST window directly, because it's not clear that VST + // hosts & clients expect to use the XEmbed protocol. + class DesktopComponent : public Component + { + public: + DesktopComponent() + { + setOpaque (true); + addToDesktop (0); + } + + void paint (Graphics& g) override + { + g.fillAll (Colours::black); + } + }; + ::Display* display = XWindowSystem::getInstance()->getDisplay(); Window pluginWindow = 0; + DesktopComponent desktopComponent; + XEmbedComponent xembedComponent { reinterpret_cast (desktopComponent.getPeer()->getNativeHandle()), true, false }; #endif #else static constexpr auto nativeScaleFactor = 1.0f;