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