diff --git a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp index 7ac4a66e14..adf53e4528 100644 --- a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp @@ -184,6 +184,35 @@ namespace #endif +#if JUCE_LINUX || JUCE_BSD +class HostDrivenEventLoop +{ +public: + HostDrivenEventLoop() + { + messageThread->stop(); + MessageManager::getInstance()->setCurrentThreadAsMessageThread(); + } + + void processPendingEvents() + { + MessageManager::getInstance()->setCurrentThreadAsMessageThread(); + + for (;;) + if (! dispatchNextMessageOnSystemQueue (true)) + return; + } + + ~HostDrivenEventLoop() + { + messageThread->start(); + } + +private: + SharedResourcePointer messageThread; +}; +#endif + //============================================================================== // Ableton Live host specific commands struct AbletonLiveHostSpecific @@ -961,6 +990,7 @@ public: case Vst2::effSetProcessPrecision: return handleSetSampleFloatType (args); case Vst2::effGetNumMidiInputChannels: return handleGetNumMidiInputChannels(); case Vst2::effGetNumMidiOutputChannels: return handleGetNumMidiOutputChannels(); + case Vst2::effEditIdle: return handleEditIdle(); default: return 0; } } @@ -1103,6 +1133,7 @@ public: void parentSizeChanged() override { updateWindowSize(); + repaint(); } void childBoundsChanged (Component*) override @@ -1127,41 +1158,11 @@ public: return {}; } - void updateWindowSize() + void resizeHostWindow (juce::Rectangle bounds) { - if (! resizingParent - && getEditorComp() != nullptr - && hostWindow != HostWindowType{}) - { - auto editorBounds = getSizeToContainChild(); - - resizeHostWindow (editorBounds.getWidth(), editorBounds.getHeight()); - - { - const ScopedValueSetter resizingParentSetter (resizingParent, true); - - #if JUCE_LINUX || JUCE_BSD // setSize() on linux causes renoise and energyxt to fail. - auto rect = convertToHostBounds ({ 0, 0, (int16) editorBounds.getHeight(), (int16) editorBounds.getWidth() }); - - X11Symbols::getInstance()->xResizeWindow (display, (Window) getWindowHandle(), - static_cast (rect.right - rect.left), - static_cast (rect.bottom - rect.top)); - #else - setSize (editorBounds.getWidth(), editorBounds.getHeight()); - #endif - } - - #if JUCE_MAC - resizeHostWindow (editorBounds.getWidth(), editorBounds.getHeight()); // (doing this a second time seems to be necessary in tracktion) - #endif - } - } - - void resizeHostWindow (int newWidth, int newHeight) - { - auto rect = convertToHostBounds ({ 0, 0, (int16) newHeight, (int16) newWidth }); - newWidth = rect.right - rect.left; - newHeight = rect.bottom - rect.top; + auto rect = convertToHostBounds ({ 0, 0, (int16) bounds.getHeight(), (int16) bounds.getWidth() }); + const auto newWidth = rect.right - rect.left; + const auto newHeight = rect.bottom - rect.top; bool sizeWasSuccessful = false; @@ -1233,6 +1234,12 @@ public: SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); #endif } + + #if JUCE_LINUX || JUCE_BSD + X11Symbols::getInstance()->xResizeWindow (display, (Window) getWindowHandle(), + static_cast (rect.right - rect.left), + static_cast (rect.bottom - rect.top)); + #endif } void setContentScaleFactor (float scale) @@ -1294,6 +1301,34 @@ public: #endif private: + void updateWindowSize() + { + if (! resizingParent + && getEditorComp() != nullptr + && hostWindow != HostWindowType{}) + { + const auto editorBounds = getSizeToContainChild(); + resizeHostWindow (editorBounds); + + { + const ScopedValueSetter resizingParentSetter (resizingParent, true); + + // setSize() on linux causes renoise and energyxt to fail. + // We'll resize our peer during resizeHostWindow() instead. + #if ! (JUCE_LINUX || JUCE_BSD) + setSize (editorBounds.getWidth(), editorBounds.getHeight()); + #endif + + if (auto* p = getPeer()) + p->updateBounds(); + } + + #if JUCE_MAC + resizeHostWindow (editorBounds); // (doing this a second time seems to be necessary in tracktion) + #endif + } + } + //============================================================================== static Vst2::ERect convertToHostBounds (const Vst2::ERect& rect) { @@ -1308,6 +1343,11 @@ public: (int16) roundToInt (rect.right * desktopScale) }; } + //============================================================================== + #if JUCE_LINUX || JUCE_BSD + SharedResourcePointer hostEventLoop; + #endif + //============================================================================== JuceVSTWrapper& wrapper; bool resizingChild = false, resizingParent = false; @@ -1616,7 +1656,11 @@ private: pointer_sized_int handleGetEditorBounds (VstOpCodeArguments args) { checkWhetherMessageThreadIsCorrect(); + #if JUCE_LINUX || JUCE_BSD + SharedResourcePointer hostDrivenEventLoop; + #else const MessageManagerLock mmLock; + #endif createEditorComp(); if (editorComp != nullptr) @@ -1632,7 +1676,11 @@ private: pointer_sized_int handleOpenEditor (VstOpCodeArguments args) { checkWhetherMessageThreadIsCorrect(); + #if JUCE_LINUX || JUCE_BSD + SharedResourcePointer hostDrivenEventLoop; + #else const MessageManagerLock mmLock; + #endif jassert (! recursionCheck); startTimerHz (4); // performs misc housekeeping chores @@ -1652,8 +1700,15 @@ private: pointer_sized_int handleCloseEditor (VstOpCodeArguments) { checkWhetherMessageThreadIsCorrect(); + + #if JUCE_LINUX || JUCE_BSD + SharedResourcePointer hostDrivenEventLoop; + #else const MessageManagerLock mmLock; + #endif + deleteEditor (true); + return 0; } @@ -2011,7 +2066,11 @@ private: pointer_sized_int handleSetContentScaleFactor (float scale) { checkWhetherMessageThreadIsCorrect(); + #if JUCE_LINUX || JUCE_BSD + SharedResourcePointer hostDrivenEventLoop; + #else const MessageManagerLock mmLock; + #endif #if ! JUCE_MAC if (! approximatelyEqual (scale, editorScaleFactor)) @@ -2076,6 +2135,16 @@ private: #endif } + pointer_sized_int handleEditIdle() + { + #if JUCE_LINUX || JUCE_BSD + SharedResourcePointer hostDrivenEventLoop; + hostDrivenEventLoop->processPendingEvents(); + #endif + + return 0; + } + //============================================================================== ScopedJuceInitialiser_GUI libraryInitialiser; @@ -2136,17 +2205,13 @@ namespace ScopedJuceInitialiser_GUI libraryInitialiser; #if JUCE_LINUX || JUCE_BSD - SharedResourcePointer messageThread; + SharedResourcePointer hostDrivenEventLoop; #endif try { if (audioMaster (nullptr, Vst2::audioMasterVersion, 0, 0, nullptr, 0) != 0) { - #if JUCE_LINUX || JUCE_BSD - MessageManagerLock mmLock; - #endif - std::unique_ptr processor { createPluginFilterOfType (AudioProcessor::wrapperType_VST) }; auto* processorPtr = processor.get(); auto* wrapper = new JuceVSTWrapper (audioMaster, std::move (processor));