| @@ -66,6 +66,13 @@ protected: | |||
| return pHost->uiName; | |||
| } | |||
| uintptr_t getUiParentId() const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0); | |||
| return pHost->uiParentId; | |||
| } | |||
| uint32_t getBufferSize() const | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0); | |||
| @@ -20,22 +20,34 @@ | |||
| #include "juce_audio_processors.h" | |||
| #include "juce_gui_extra.h" | |||
| #ifdef HAVE_X11 | |||
| # include <X11/Xlib.h> | |||
| # undef KeyPress | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| namespace juce { | |||
| #include "jucepluginhost/juce_MidiKeyboardComponent.h" | |||
| #include "jucepluginhost/juce_MidiKeyboardComponent.cpp" | |||
| } | |||
| using namespace juce; | |||
| // ----------------------------------------------------------------------- | |||
| #include "jucepluginhost/FilterGraph.h" | |||
| #include "jucepluginhost/InternalFilters.h" | |||
| #include "jucepluginhost/GraphEditorPanel.h" | |||
| #include "jucepluginhost/MainHostWindow.h" | |||
| #include "jucepluginhost/FilterGraph.cpp" | |||
| #include "jucepluginhost/InternalFilters.cpp" | |||
| #include "jucepluginhost/GraphEditorPanel.cpp" | |||
| #include "jucepluginhost/MainHostWindow.cpp" | |||
| #ifdef HAVE_X11 | |||
| extern Display* display; | |||
| #endif | |||
| } | |||
| using namespace juce; | |||
| // ----------------------------------------------------------------------- | |||
| class JucePatchbayPlugin : public NativePluginClass | |||
| @@ -152,6 +164,13 @@ protected: | |||
| { | |||
| fWindow = new MainHostWindow(fFormatManager, fGraph, *fAppProperties); | |||
| fWindow->setName(getUiName()); | |||
| #ifdef HAVE_X11 | |||
| ::Window thisWinId = (::Window)fWindow->getWindowHandle(); | |||
| ::Window hostWinId = (::Window)getUiParentId(); | |||
| if (display != nullptr && thisWinId != 0 && hostWinId != 0) | |||
| XSetTransientForHint(display, thisWinId, hostWinId); | |||
| #endif | |||
| } | |||
| { | |||
| const ScopedLock csl(fMidiKeyMutex); | |||
| @@ -242,7 +261,7 @@ private: | |||
| static const NativePluginDescriptor jucepatchbayDesc = { | |||
| /* category */ PLUGIN_CATEGORY_UTILITY, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_SYNTH|PLUGIN_HAS_UI|PLUGIN_NEEDS_FIXED_BUFFERS|PLUGIN_NEEDS_UI_JUCE|PLUGIN_USES_STATE/*|PLUGIN_USES_TIME*/), | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_SYNTH|PLUGIN_HAS_UI|PLUGIN_NEEDS_FIXED_BUFFERS|PLUGIN_NEEDS_UI_JUCE|PLUGIN_USES_STATE/*|PLUGIN_USES_TIME*/|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| @@ -266,10 +285,3 @@ void carla_register_native_plugin_jucepatchbay() | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| #include "jucepluginhost/FilterGraph.cpp" | |||
| #include "jucepluginhost/InternalFilters.cpp" | |||
| #include "jucepluginhost/GraphEditorPanel.cpp" | |||
| #include "jucepluginhost/MainHostWindow.cpp" | |||
| // ----------------------------------------------------------------------- | |||
| @@ -347,6 +347,9 @@ protected: | |||
| } | |||
| fWindow->show(fView); | |||
| if (const uintptr_t winId = getUiParentId()) | |||
| fWindow->setTransientWinId(winId); | |||
| } | |||
| else if (fWindow != nullptr) | |||
| { | |||
| @@ -820,7 +823,7 @@ private: | |||
| static const NativePluginDescriptor vexArpDesc = { | |||
| /* category */ PLUGIN_CATEGORY_UTILITY, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_HAS_UI|PLUGIN_NEEDS_UI_JUCE|PLUGIN_USES_TIME), | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_HAS_UI|PLUGIN_NEEDS_UI_JUCE|PLUGIN_USES_TIME|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(PLUGIN_SUPPORTS_EVERYTHING), | |||
| /* audioIns */ 0, | |||
| /* audioOuts */ 0, | |||
| @@ -1033,6 +1033,9 @@ protected: | |||
| fView = new VexEditorComponent(this, fArpSet1, fArpSet2, fArpSet3); | |||
| fWindow->show(fView); | |||
| if (const uintptr_t winId = getUiParentId()) | |||
| fWindow->setTransientWinId(winId); | |||
| } | |||
| else if (fWindow != nullptr) | |||
| { | |||
| @@ -1220,7 +1223,7 @@ private: | |||
| static const NativePluginDescriptor vexsynthDesc = { | |||
| /* category */ PLUGIN_CATEGORY_SYNTH, | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_SYNTH|PLUGIN_HAS_UI|PLUGIN_NEEDS_UI_JUCE|PLUGIN_USES_STATE|PLUGIN_USES_TIME), | |||
| /* hints */ static_cast<NativePluginHints>(PLUGIN_IS_SYNTH|PLUGIN_HAS_UI|PLUGIN_NEEDS_UI_JUCE|PLUGIN_USES_STATE|PLUGIN_USES_TIME|PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ 0, | |||
| /* audioOuts */ 2, | |||
| @@ -88,7 +88,7 @@ public: | |||
| void processBlock(AudioSampleBuffer* const outBuffer) | |||
| { | |||
| processBlock(outBuffer->getSampleData(0, 0), outBuffer->getSampleData(1, 0), outBuffer->getNumSamples()); | |||
| processBlock(outBuffer->getWritePointer(0), outBuffer->getWritePointer(1), outBuffer->getNumSamples()); | |||
| } | |||
| void processBlock(float* const outBufferL, float* const outBufferR, const int numSamples) | |||
| @@ -99,8 +99,8 @@ public: | |||
| const int delay = int(cycle * 0.5f); | |||
| const float lfoC = 2.0f * sinf(float_Pi * (speed * 5.0f) / sampleRate); | |||
| float* const bufferL = buffer.getSampleData(0, 0); | |||
| float* const bufferR = buffer.getSampleData(1, 0); | |||
| float* const bufferL = buffer.getWritePointer(0); | |||
| float* const bufferR = buffer.getWritePointer(1); | |||
| float a, b, alpha, readpoint; | |||
| int rp; | |||
| @@ -83,7 +83,7 @@ public: | |||
| void processBlock(AudioSampleBuffer* const outBuffer, double bpm) | |||
| { | |||
| processBlock(outBuffer->getSampleData(0, 0), outBuffer->getSampleData(1, 0), outBuffer->getNumSamples(), bpm); | |||
| processBlock(outBuffer->getWritePointer(0), outBuffer->getWritePointer(1), outBuffer->getNumSamples(), bpm); | |||
| } | |||
| void processBlock(float* const outBufferL, float* const outBufferR, const int numSamples, double bpm) | |||
| @@ -93,8 +93,8 @@ public: | |||
| const int delay = jmin(int(parameters[73] * 8.0f) * int(((60.0 / bpm) * sampleRate) / 4.0), 44100); | |||
| const float feedback = parameters[74]; | |||
| float* const bufferL = buffer.getSampleData(0, 0); | |||
| float* const bufferR = buffer.getSampleData(1, 0); | |||
| float* const bufferL = buffer.getWritePointer(0); | |||
| float* const bufferR = buffer.getWritePointer(1); | |||
| for (int i = 0; i < numSamples; ++i) | |||
| { | |||
| @@ -64,7 +64,7 @@ public: | |||
| void processBlock(AudioSampleBuffer* const outBuffer) | |||
| { | |||
| processBlock(outBuffer->getSampleData(0, 0), outBuffer->getSampleData(1, 0), outBuffer->getNumSamples()); | |||
| processBlock(outBuffer->getWritePointer(0), outBuffer->getWritePointer(1), outBuffer->getNumSamples()); | |||
| } | |||
| void processBlock(float* const outBufferL, float* const outBufferR, const int numSamples) | |||
| @@ -80,8 +80,8 @@ public: | |||
| void doProcess(AudioSampleBuffer& obf, AudioSampleBuffer& assbf, AudioSampleBuffer& ebf1, AudioSampleBuffer& ebf2, AudioSampleBuffer& ebf3) | |||
| { | |||
| const int numSamples = obf.getNumSamples(); | |||
| float* const outPtrL = assbf.getSampleData(0,0); | |||
| float* const outPtrR = assbf.getSampleData(1,0); | |||
| float* const outPtrL = assbf.getWritePointer(0); | |||
| float* const outPtrR = assbf.getWritePointer(1); | |||
| if (part1) | |||
| { | |||
| @@ -47,17 +47,17 @@ MyLookAndFeel::MyLookAndFeel() | |||
| // Topaz->setHorizontalScale (1.0f); | |||
| } | |||
| MyLookAndFeel::~MyLookAndFeel() | |||
| MyLookAndFeel::~MyLookAndFeel() override | |||
| { | |||
| delete Topaz; | |||
| } | |||
| Font MyLookAndFeel::getComboBoxFont (ComboBox& box) | |||
| Font MyLookAndFeel::getComboBoxFont(ComboBox&) override | |||
| { | |||
| return *Topaz; | |||
| } | |||
| Font MyLookAndFeel::getPopupMenuFont() | |||
| Font MyLookAndFeel::getPopupMenuFont() override | |||
| { | |||
| return *Topaz; | |||
| } | |||
| @@ -66,7 +66,7 @@ void MyLookAndFeel::getIdealPopupMenuItemSize(const String& text, | |||
| const bool isSeparator, | |||
| int standardMenuItemHeight, | |||
| int& idealWidth, | |||
| int& idealHeight) | |||
| int& idealHeight) override | |||
| { | |||
| if (isSeparator) | |||
| { | |||
| @@ -86,7 +86,7 @@ void MyLookAndFeel::getIdealPopupMenuItemSize(const String& text, | |||
| void MyLookAndFeel::drawToggleButton(Graphics& g, | |||
| ToggleButton& button, | |||
| bool isMouseOverButton, | |||
| bool isButtonDown) | |||
| bool isButtonDown) override | |||
| { | |||
| const int tickWidth = jmin (20, button.getHeight() - 4); | |||
| @@ -108,13 +108,13 @@ void MyLookAndFeel::drawToggleButton(Graphics& g, | |||
| Justification::centredLeft, 10); | |||
| } | |||
| void MyLookAndFeel::drawRotarySlider (Graphics& g, | |||
| int x, int y, | |||
| int width, int height, | |||
| float sliderPos, | |||
| const float rotaryStartAngle, | |||
| const float rotaryEndAngle, | |||
| Slider& slider) | |||
| void MyLookAndFeel::drawRotarySlider(Graphics& g, | |||
| int x, int y, | |||
| int width, int height, | |||
| float sliderPos, | |||
| const float rotaryStartAngle, | |||
| const float rotaryEndAngle, | |||
| Slider& slider) override | |||
| { | |||
| const float radius = jmin (width / 2, height / 2) - 2.0f; | |||
| const float centreX = x + width * 0.5f; | |||
| @@ -50,31 +50,31 @@ class MyLookAndFeel : public LookAndFeel_V2 | |||
| { | |||
| public: | |||
| MyLookAndFeel(); | |||
| ~MyLookAndFeel(); | |||
| Font getComboBoxFont (ComboBox& box); | |||
| Font getPopupMenuFont(); | |||
| void getIdealPopupMenuItemSize (const String& text, | |||
| const bool isSeparator, | |||
| int standardMenuItemHeight, | |||
| int& idealWidth, | |||
| int& idealHeight); | |||
| void drawToggleButton (Graphics& g, | |||
| ToggleButton& button, | |||
| bool isMouseOverButton, | |||
| bool isButtonDown); | |||
| void drawRotarySlider (Graphics& g, | |||
| int x, int y, | |||
| int width, int height, | |||
| float sliderPosProportional, | |||
| const float rotaryStartAngle, | |||
| const float rotaryEndAngle, | |||
| Slider& slider); | |||
| ~MyLookAndFeel() override; | |||
| juce::Font getComboBoxFont (ComboBox& box) override; | |||
| juce::Font getPopupMenuFont() override; | |||
| void getIdealPopupMenuItemSize(const String& text, | |||
| const bool isSeparator, | |||
| int standardMenuItemHeight, | |||
| int& idealWidth, | |||
| int& idealHeight) override; | |||
| void drawToggleButton(Graphics& g, | |||
| ToggleButton& button, | |||
| bool isMouseOverButton, | |||
| bool isButtonDown) override; | |||
| void drawRotarySlider(Graphics& g, | |||
| int x, int y, | |||
| int width, int height, | |||
| float sliderPosProportional, | |||
| const float rotaryStartAngle, | |||
| const float rotaryEndAngle, | |||
| Slider& slider) override; | |||
| public: | |||
| Font* Topaz; | |||
| juce::Font* Topaz; | |||
| }; | |||
| #endif | |||
| @@ -18,12 +18,22 @@ | |||
| #ifndef JUCE_PLUGIN_WINDOW_HPP_INCLUDED | |||
| #define JUCE_PLUGIN_WINDOW_HPP_INCLUDED | |||
| #include "CarlaUtils.hpp" | |||
| #include "juce_gui_basics.h" | |||
| #ifdef HAVE_X11 | |||
| # include <X11/Xlib.h> | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| namespace juce { | |||
| #ifdef HAVE_X11 | |||
| extern Display* display; | |||
| #endif | |||
| class JucePluginWindow : public DocumentWindow | |||
| { | |||
| public: | |||
| @@ -70,6 +80,21 @@ public: | |||
| return fClosed; | |||
| } | |||
| void setTransientWinId(const uintptr_t winId) const override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(winId != 0,); | |||
| #ifdef HAVE_X11 | |||
| CARLA_SAFE_ASSERT_RETURN(display != nullptr,); | |||
| ::Window window = (::Window)getWindowHandle(); | |||
| CARLA_SAFE_ASSERT_RETURN(window != 0,); | |||
| XSetTransientForHint(display, window, static_cast<Window>(winId)); | |||
| #endif | |||
| } | |||
| protected: | |||
| void closeButtonPressed() override | |||
| { | |||