Browse Source

Handle VST3 UI resize

Signed-off-by: falkTX <falktx@falktx.com>
pull/1775/head
falkTX 2 years ago
parent
commit
b19d3daad2
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
5 changed files with 324 additions and 91 deletions
  1. +13
    -7
      source/backend/plugin/CarlaPluginCLAP.cpp
  2. +218
    -29
      source/backend/plugin/CarlaPluginVST3.cpp
  3. +84
    -55
      source/utils/CarlaPluginUI.cpp
  4. +1
    -0
      source/utils/CarlaPluginUI.hpp
  5. +8
    -0
      source/utils/CarlaVst3Utils.hpp

+ 13
- 7
source/backend/plugin/CarlaPluginCLAP.cpp View File

@@ -1,6 +1,6 @@
/* /*
* Carla CLAP Plugin * Carla CLAP Plugin
* Copyright (C) 2022 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2022-2023 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@@ -1562,7 +1562,8 @@ public:


portName.truncate(portNameSize); portName.truncate(portNameSize);


pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio,
portName, true, j);
pData->audioIn.ports[j].rindex = j; pData->audioIn.ports[j].rindex = j;
} }


@@ -1587,7 +1588,8 @@ public:


portName.truncate(portNameSize); portName.truncate(portNameSize);


pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio,
portName, false, j);
pData->audioOut.ports[j].rindex = j; pData->audioOut.ports[j].rindex = j;
} }


@@ -1617,7 +1619,8 @@ public:


portName += portInfo.name; portName += portInfo.name;
portName.truncate(portNameSize); portName.truncate(portNameSize);
fInputEvents.portData[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j);
fInputEvents.portData[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent,
portName, true, j);
} }
else else
{ {
@@ -1654,7 +1657,8 @@ public:


portName += portInfo.name; portName += portInfo.name;
portName.truncate(portNameSize); portName.truncate(portNameSize);
fOutputEvents.portData[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j);
fOutputEvents.portData[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent,
portName, false, j);
} }
else else
{ {
@@ -1764,7 +1768,8 @@ public:
portName += "events-in"; portName += "events-in";
portName.truncate(portNameSize); portName.truncate(portNameSize);


pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent,
portName, true, 0);
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
pData->event.cvSourcePorts = pData->client->createCVSourcePorts(); pData->event.cvSourcePorts = pData->client->createCVSourcePorts();
#endif #endif
@@ -1786,7 +1791,8 @@ public:
portName += "events-out"; portName += "events-out";
portName.truncate(portNameSize); portName.truncate(portNameSize);


pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent,
portName, false, 0);


if (mOuts == 1) if (mOuts == 1)
fOutputEvents.portData[0].port = pData->event.portOut; fOutputEvents.portData[0].port = pData->event.portOut;


+ 218
- 29
source/backend/plugin/CarlaPluginVST3.cpp View File

@@ -1279,6 +1279,40 @@ public:
// ---------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------
// Information (current data) // Information (current data)


uint getAudioPortHints(const bool isOutput, const uint32_t portIndex) const noexcept override
{
uint hints = 0x0;

if (isOutput)
{
const uint32_t numOutputs = static_cast<uint32_t>(fBuses.numOutputs);

for (uint32_t b=0, i=0; b < numOutputs; ++b, i += fBuses.outputs[b].num_channels)
{
if (i != portIndex)
continue;

if (fBuses.outputInfo[i].bus_type == V3_AUX)
hints |= AUDIO_PORT_IS_SIDECHAIN;
}
}
else
{
const uint32_t numInputs = static_cast<uint32_t>(fBuses.numInputs);

for (uint32_t b=0, i=0; b < numInputs; ++b, i += fBuses.inputs[b].num_channels)
{
if (i != portIndex)
continue;

if (fBuses.inputInfo[i].bus_type == V3_AUX)
hints |= AUDIO_PORT_IS_SIDECHAIN;
}
}

return hints;
}

std::size_t getChunkData(void** const dataPtr) noexcept override std::size_t getChunkData(void** const dataPtr) noexcept override
{ {
CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0); CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
@@ -1578,31 +1612,34 @@ public:


if (fUI.window == nullptr) if (fUI.window == nullptr)
{ {
const char* msg = nullptr;
const EngineOptions& opts(pData->engine->getOptions()); const EngineOptions& opts(pData->engine->getOptions());


#if defined(CARLA_OS_MAC)
fUI.window = CarlaPluginUI::newCocoa(this, opts.frontendWinId, opts.pluginsAreStandalone, false);
#elif defined(CARLA_OS_WIN)
fUI.window = CarlaPluginUI::newWindows(this, opts.frontendWinId, opts.pluginsAreStandalone, false);
#elif defined(HAVE_X11)
fUI.window = CarlaPluginUI::newX11(this, opts.frontendWinId, opts.pluginsAreStandalone, false, false);
#else
msg = "Unsupported UI type";
#endif
const bool isStandalone = opts.pluginsAreStandalone;
const bool isResizable = v3_cpp_obj(fV3.view)->can_resize(fV3.view) == V3_TRUE;


if (fUI.window == nullptr)
return pData->engine->callback(true, true,
ENGINE_CALLBACK_UI_STATE_CHANGED,
pData->id,
-1,
0, 0, 0.0f,
msg);
#if defined(CARLA_OS_MAC)
fUI.window = CarlaPluginUI::newCocoa(this, opts.frontendWinId, isStandalone, isResizable);
#elif defined(CARLA_OS_WIN)
fUI.window = CarlaPluginUI::newWindows(this, opts.frontendWinId, isStandalone, isResizable);
#elif defined(HAVE_X11)
fUI.window = CarlaPluginUI::newX11(this, opts.frontendWinId, isStandalone, isResizable, false);
#else
pData->engine->callback(true, true,
ENGINE_CALLBACK_UI_STATE_CHANGED,
pData->id,
-1,
0, 0, 0.0f,
"Unsupported UI type");
return;
#endif


fUI.window->setTitle(uiTitle.buffer()); fUI.window->setTitle(uiTitle.buffer());


#ifndef CARLA_OS_MAC #ifndef CARLA_OS_MAC
// TODO inform plugin of what UI scale we use
if (carla_isNotZero(opts.uiScale))
{
// TODO inform plugin of what UI scale we use
}
#endif #endif


v3_cpp_obj(fV3.view)->set_frame(fV3.view, (v3_plugin_frame**)&fPluginFramePtr); v3_cpp_obj(fV3.view)->set_frame(fV3.view, (v3_plugin_frame**)&fPluginFramePtr);
@@ -1611,7 +1648,6 @@ public:
V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_OK) V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_OK)
{ {
v3_view_rect rect = {}; v3_view_rect rect = {};

if (v3_cpp_obj(fV3.view)->get_size(fV3.view, &rect) == V3_OK) if (v3_cpp_obj(fV3.view)->get_size(fV3.view, &rect) == V3_OK)
{ {
const int32_t width = rect.right - rect.left; const int32_t width = rect.right - rect.left;
@@ -1621,12 +1657,37 @@ public:
CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height); CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height);


if (width > 1 && height > 1) if (width > 1 && height > 1)
{
fUI.isResizingFromInit = true;
fUI.width = width;
fUI.height = height;
fUI.window->setSize(static_cast<uint>(width), static_cast<uint>(height), true, true); fUI.window->setSize(static_cast<uint>(width), static_cast<uint>(height), true, true);
}
} }
else else
{ {
carla_stdout("view attached ok, size failed"); carla_stdout("view attached ok, size failed");
} }

if (isResizable)
{
carla_zeroStruct(rect);
if (v3_cpp_obj(fV3.view)->check_size_constraint(fV3.view, &rect) == V3_OK)
{
const int32_t width = rect.right - rect.left;
const int32_t height = rect.bottom - rect.top;
carla_stdout("size constraint ok %i %i", width, height);

CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height);

if (width > 1 && height > 1)
fUI.window->setMinimumSize(static_cast<uint>(width), static_cast<uint>(height));
}
else
{
carla_stdout("view attached ok, size constraint failed");
}
}
} }
else else
{ {
@@ -1698,10 +1759,15 @@ public:
CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height); CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height);


if (width > 1 && height > 1) if (width > 1 && height > 1)
{
fUI.isResizingFromInit = true;
fUI.width = width;
fUI.height = height;
pData->engine->callback(true, true, pData->engine->callback(true, true,
ENGINE_CALLBACK_EMBED_UI_RESIZED, ENGINE_CALLBACK_EMBED_UI_RESIZED,
pData->id, width, height, pData->id, width, height,
0, 0.0f, nullptr); 0, 0.0f, nullptr);
}
} }
else else
{ {
@@ -1807,11 +1873,29 @@ public:


void uiIdle() override void uiIdle() override
{ {
if (!kEngineHasIdleOnMainThread)
runIdleCallbacksAsNeeded(true);

if (fUI.window != nullptr) if (fUI.window != nullptr)
fUI.window->idle(); fUI.window->idle();


if (!kEngineHasIdleOnMainThread)
runIdleCallbacksAsNeeded(true);
if (fUI.isResizingFromHost)
{
fUI.isResizingFromHost = false;

// if (!fUI.isResizingFromPlugin && !fUI.isResizingFromInit)
{
carla_stdout("Host resize stopped");
// v3_view_rect rect = { 0, 0, static_cast<int32_t>(fUI.width), static_cast<int32_t>(fUI.height) };
// v3_cpp_obj(fV3.view)->on_size(fV3.view, &rect);
}
}

if (fUI.isResizingFromPlugin)
{
fUI.isResizingFromPlugin = false;
carla_stdout("Plugin resize stopped");
}


CarlaPlugin::uiIdle(); CarlaPlugin::uiIdle();
} }
@@ -1857,8 +1941,11 @@ public:


for (int32_t b=0; b<numAudioInputBuses; ++b) for (int32_t b=0; b<numAudioInputBuses; ++b)
{ {
v3_bus_info busInfo = {};
carla_zeroStruct(fBuses.inputs[b]); carla_zeroStruct(fBuses.inputs[b]);
carla_zeroStruct(fBuses.inputInfo[b]);
fBuses.inputInfo[b].offset = aIns + cvIns;

v3_bus_info busInfo = {};
CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->get_bus_info(fV3.component, CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->get_bus_info(fV3.component,
V3_AUDIO, V3_INPUT, b, &busInfo) == V3_OK); V3_AUDIO, V3_INPUT, b, &busInfo) == V3_OK);


@@ -1871,6 +1958,8 @@ public:
} }


fBuses.inputs[b].num_channels = numChannels; fBuses.inputs[b].num_channels = numChannels;
fBuses.inputInfo[b].bus_type = busInfo.bus_type;
fBuses.inputInfo[b].flags = busInfo.flags;


if (busInfo.flags & V3_IS_CONTROL_VOLTAGE) if (busInfo.flags & V3_IS_CONTROL_VOLTAGE)
cvIns += static_cast<uint32_t>(numChannels); cvIns += static_cast<uint32_t>(numChannels);
@@ -1880,8 +1969,11 @@ public:


for (int32_t b=0; b<numAudioOutputBuses; ++b) for (int32_t b=0; b<numAudioOutputBuses; ++b)
{ {
v3_bus_info busInfo = {};
carla_zeroStruct(fBuses.outputs[b]); carla_zeroStruct(fBuses.outputs[b]);
carla_zeroStruct(fBuses.inputInfo[b]);
fBuses.outputInfo[b].offset = aOuts + cvOuts;

v3_bus_info busInfo = {};
CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->get_bus_info(fV3.component, CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->get_bus_info(fV3.component,
V3_AUDIO, V3_OUTPUT, b, &busInfo) == V3_OK); V3_AUDIO, V3_OUTPUT, b, &busInfo) == V3_OK);


@@ -1894,6 +1986,8 @@ public:
} }


fBuses.outputs[b].num_channels = numChannels; fBuses.outputs[b].num_channels = numChannels;
fBuses.outputInfo[b].bus_type = busInfo.bus_type;
fBuses.outputInfo[b].flags = busInfo.flags;


if (busInfo.flags & V3_IS_CONTROL_VOLTAGE) if (busInfo.flags & V3_IS_CONTROL_VOLTAGE)
cvOuts += static_cast<uint32_t>(numChannels); cvOuts += static_cast<uint32_t>(numChannels);
@@ -3349,6 +3443,7 @@ protected:


v3_result v3ResizeView(struct v3_plugin_view** const view, struct v3_view_rect* const rect) override v3_result v3ResizeView(struct v3_plugin_view** const view, struct v3_view_rect* const rect) override
{ {
CARLA_SAFE_ASSERT_RETURN(fV3.view != nullptr, V3_INVALID_ARG);
CARLA_SAFE_ASSERT_RETURN(fV3.view == view, V3_INVALID_ARG); CARLA_SAFE_ASSERT_RETURN(fV3.view == view, V3_INVALID_ARG);


const int32_t width = rect->right - rect->left; const int32_t width = rect->right - rect->left;
@@ -3356,6 +3451,12 @@ protected:
CARLA_SAFE_ASSERT_INT_RETURN(width > 0, width, V3_INVALID_ARG); CARLA_SAFE_ASSERT_INT_RETURN(width > 0, width, V3_INVALID_ARG);
CARLA_SAFE_ASSERT_INT_RETURN(height > 0, height, V3_INVALID_ARG); CARLA_SAFE_ASSERT_INT_RETURN(height > 0, height, V3_INVALID_ARG);


carla_stdout("v3ResizeView %d %d", width, height);

fUI.isResizingFromPlugin = true;
fUI.width = width;
fUI.height = height;

if (fUI.isEmbed) if (fUI.isEmbed)
{ {
pData->engine->callback(true, true, pData->engine->callback(true, true,
@@ -3378,6 +3479,9 @@ protected:
// CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,); // CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
carla_debug("CarlaPluginVST3::handlePluginUIClosed()"); carla_debug("CarlaPluginVST3::handlePluginUIClosed()");


fUI.isResizingFromHost = fUI.isResizingFromInit = false;
fUI.isResizingFromPlugin = false;

showCustomUI(false); showCustomUI(false);
pData->engine->callback(true, true, pData->engine->callback(true, true,
ENGINE_CALLBACK_UI_STATE_CHANGED, ENGINE_CALLBACK_UI_STATE_CHANGED,
@@ -3388,11 +3492,60 @@ protected:


void handlePluginUIResized(const uint width, const uint height) override void handlePluginUIResized(const uint width, const uint height) override
{ {
CARLA_SAFE_ASSERT_RETURN(fV3.view != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,); CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
carla_debug("CarlaPluginVST3::handlePluginUIResized(%u, %u)", width, height);
carla_stdout("CarlaPluginVST3::handlePluginUIResized(%u, %u | vs %u %u) %s %s %s",
width, height,
fUI.width, fUI.height,
bool2str(fUI.isResizingFromPlugin),
bool2str(fUI.isResizingFromInit),
bool2str(fUI.isResizingFromHost));

if (fUI.isResizingFromInit)
{
CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.width == width, fUI.width, width,);
CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.height == height, fUI.height, height,);
fUI.isResizingFromInit = false;
return;
}

if (fUI.isResizingFromPlugin)
{
CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.width == width, fUI.width, width,);
CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.height == height, fUI.height, height,);
fUI.isResizingFromPlugin = false;
return;
}


return; // unused
(void)width; (void)height;
if (fUI.isResizingFromHost)
{
CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.width == width, fUI.width, width,);
CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.height == height, fUI.height, height,);
fUI.isResizingFromHost = false;
return;
}

if (fUI.width != width || fUI.height != height)
{
v3_view_rect rect = { 0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height) };
if (v3_cpp_obj(fV3.view)->check_size_constraint(fV3.view, &rect) == V3_OK)
{
const uint width2 = rect.right - rect.left;
const uint height2 = rect.bottom - rect.top;

if (width2 != width || height2 != height)
{
fUI.isResizingFromHost = true;
fUI.width = width2;
fUI.height = height2;
fUI.window->setSize(width2, height2, true, false);
}
else
{
v3_cpp_obj(fV3.view)->on_size(fV3.view, &rect);
}
}
}
} }


private: private:
@@ -3680,29 +3833,56 @@ private:
int32_t numOutputs; int32_t numOutputs;
v3_audio_bus_buffers* inputs; v3_audio_bus_buffers* inputs;
v3_audio_bus_buffers* outputs; v3_audio_bus_buffers* outputs;
v3_bus_mini_info* inputInfo;
v3_bus_mini_info* outputInfo;


Buses() Buses()
: numInputs(0), : numInputs(0),
numOutputs(0), numOutputs(0),
inputs(nullptr), inputs(nullptr),
outputs(nullptr) {}
outputs(nullptr),
inputInfo(nullptr),
outputInfo(nullptr) {}


~Buses() ~Buses()
{ {
delete[] inputs; delete[] inputs;
delete[] outputs; delete[] outputs;
delete[] inputInfo;
delete[] outputInfo;
} }


void createNew(const int32_t numAudioInputBuses, const int32_t numAudioOutputBuses) void createNew(const int32_t numAudioInputBuses, const int32_t numAudioOutputBuses)
{ {
delete[] inputs; delete[] inputs;
delete[] outputs; delete[] outputs;
delete[] inputInfo;
delete[] outputInfo;


numInputs = numAudioInputBuses; numInputs = numAudioInputBuses;
numOutputs = numAudioOutputBuses; numOutputs = numAudioOutputBuses;


inputs = numAudioInputBuses > 0 ? new v3_audio_bus_buffers[numAudioInputBuses] : nullptr;
outputs = numAudioOutputBuses > 0 ? new v3_audio_bus_buffers[numAudioOutputBuses] : nullptr;
if (numAudioInputBuses > 0)
{
inputs = new v3_audio_bus_buffers[numAudioInputBuses];
inputInfo = new v3_bus_mini_info[numAudioInputBuses];
}
else
{
inputs = nullptr;
inputInfo = nullptr;
}

if (numAudioOutputBuses > 0)
{
outputs = new v3_audio_bus_buffers[numAudioOutputBuses];
outputInfo = new v3_bus_mini_info[numAudioOutputBuses];
}
else
{
outputs = nullptr;
outputInfo = nullptr;
}
} }


CARLA_DECLARE_NON_COPYABLE(Buses) CARLA_DECLARE_NON_COPYABLE(Buses)
@@ -3752,13 +3932,22 @@ private:
struct UI { struct UI {
bool isAttached; bool isAttached;
bool isEmbed; bool isEmbed;
bool isResizingFromHost;
bool isResizingFromInit;
bool isResizingFromPlugin;
bool isVisible; bool isVisible;
uint32_t width, height;
CarlaPluginUI* window; CarlaPluginUI* window;


UI() noexcept UI() noexcept
: isAttached(false), : isAttached(false),
isEmbed(false), isEmbed(false),
isResizingFromHost(false),
isResizingFromInit(false),
isResizingFromPlugin(false),
isVisible(false), isVisible(false),
width(0),
height(0),
window(nullptr) {} window(nullptr) {}


~UI() ~UI()


+ 84
- 55
source/utils/CarlaPluginUI.cpp View File

@@ -45,9 +45,11 @@
// X11 // X11


#ifdef HAVE_X11 #ifdef HAVE_X11
static constexpr const uint X11Key_Escape = 9;

typedef void (*EventProcPtr)(XEvent* ev); typedef void (*EventProcPtr)(XEvent* ev);


static const uint X11Key_Escape = 9;
// FIXME put all this inside a scoped class
static bool gErrorTriggered = false; static bool gErrorTriggered = false;
# if defined(__GNUC__) && (__GNUC__ >= 5) && ! defined(__clang__) # if defined(__GNUC__) && (__GNUC__ >= 5) && ! defined(__clang__)
# pragma GCC diagnostic push # pragma GCC diagnostic push
@@ -78,6 +80,8 @@ public:
fIsVisible(false), fIsVisible(false),
fFirstShow(true), fFirstShow(true),
fSetSizeCalledAtLeastOnce(false), fSetSizeCalledAtLeastOnce(false),
fMinimumWidth(0),
fMinimumHeight(0),
fEventProc(nullptr) fEventProc(nullptr)
{ {
fDisplay = XOpenDisplay(nullptr); fDisplay = XOpenDisplay(nullptr);
@@ -165,8 +169,7 @@ public:
int width = 0; int width = 0;
int height = 0; int height = 0;


XWindowAttributes attrs;
carla_zeroStruct(attrs);
XWindowAttributes attrs = {};


pthread_mutex_lock(&gErrorMutex); pthread_mutex_lock(&gErrorMutex);
const XErrorHandler oldErrorHandler = XSetErrorHandler(temporaryErrorHandler); const XErrorHandler oldErrorHandler = XSetErrorHandler(temporaryErrorHandler);
@@ -183,8 +186,7 @@ public:


if (width == 0 && height == 0) if (width == 0 && height == 0)
{ {
XSizeHints sizeHints;
carla_zeroStruct(sizeHints);
XSizeHints sizeHints = {};


if (XGetNormalHints(fDisplay, childWindow, &sizeHints)) if (XGetNormalHints(fDisplay, childWindow, &sizeHints))
{ {
@@ -252,8 +254,11 @@ public:
// prevent recursion // prevent recursion
if (fIsIdling) return; if (fIsIdling) return;


int nextWidth = 0;
int nextHeight = 0;
uint nextChildWidth = 0;
uint nextChildHeight = 0;

uint nextHostWidth = 0;
uint nextHostHeight = 0;


fIsIdling = true; fIsIdling = true;


@@ -273,47 +278,15 @@ public:
CARLA_SAFE_ASSERT_CONTINUE(event.xconfigure.width > 0); CARLA_SAFE_ASSERT_CONTINUE(event.xconfigure.width > 0);
CARLA_SAFE_ASSERT_CONTINUE(event.xconfigure.height > 0); CARLA_SAFE_ASSERT_CONTINUE(event.xconfigure.height > 0);


if (event.xconfigure.window == fHostWindow)
if (event.xconfigure.window == fHostWindow && fHostWindow != 0)
{ {
const uint width = static_cast<uint>(event.xconfigure.width);
const uint height = static_cast<uint>(event.xconfigure.height);

if (fChildWindow != 0)
{
if (! fChildWindowConfigured)
{
pthread_mutex_lock(&gErrorMutex);
const XErrorHandler oldErrorHandler = XSetErrorHandler(temporaryErrorHandler);
gErrorTriggered = false;

XSizeHints sizeHints;
carla_zeroStruct(sizeHints);

if (XGetNormalHints(fDisplay, fChildWindow, &sizeHints) && !gErrorTriggered)
{
XSetNormalHints(fDisplay, fHostWindow, &sizeHints);
}
else
{
carla_stdout("Caught errors while accessing child window");
fChildWindow = 0;
}

fChildWindowConfigured = true;
XSetErrorHandler(oldErrorHandler);
pthread_mutex_unlock(&gErrorMutex);
}

if (fChildWindow != 0)
XResizeWindow(fDisplay, fChildWindow, width, height);
}

fCallback->handlePluginUIResized(width, height);
nextHostWidth = static_cast<uint>(event.xconfigure.width);
nextHostHeight = static_cast<uint>(event.xconfigure.height);
} }
else if (fChildWindowMonitoring && event.xconfigure.window == fChildWindow && fChildWindow != 0)
else if (event.xconfigure.window == fChildWindow && fChildWindow != 0)
{ {
nextWidth = event.xconfigure.width;
nextHeight = event.xconfigure.height;
nextChildWidth = static_cast<uint>(event.xconfigure.width);
nextChildHeight = static_cast<uint>(event.xconfigure.height);
} }
break; break;


@@ -341,6 +314,7 @@ public:
case FocusIn: case FocusIn:
if (fChildWindow == 0) if (fChildWindow == 0)
fChildWindow = getChildWindow(); fChildWindow = getChildWindow();

if (fChildWindow != 0) if (fChildWindow != 0)
{ {
XWindowAttributes wa; XWindowAttributes wa;
@@ -358,16 +332,24 @@ public:
fEventProc(&event); fEventProc(&event);
} }


if (nextWidth != 0 && nextHeight != 0 && fChildWindow != 0)
if (nextChildWidth != 0 && nextChildHeight != 0 && fChildWindow != 0)
{ {
XSizeHints sizeHints;
carla_zeroStruct(sizeHints);
applyHintsFromChildWindow();
XResizeWindow(fDisplay, fHostWindow, nextChildWidth, nextChildHeight);
// XFlush(fDisplay);
}
else if (nextHostWidth != 0 && nextHostHeight != 0)
{
if (fChildWindow != 0 && ! fChildWindowConfigured)
{
applyHintsFromChildWindow();
fChildWindowConfigured = true;
}


if (XGetNormalHints(fDisplay, fChildWindow, &sizeHints))
XSetNormalHints(fDisplay, fHostWindow, &sizeHints);
if (fChildWindow != 0)
XResizeWindow(fDisplay, fChildWindow, nextHostWidth, nextHostHeight);


XResizeWindow(fDisplay, fHostWindow, static_cast<uint>(nextWidth), static_cast<uint>(nextHeight));
XFlush(fDisplay);
fCallback->handlePluginUIResized(nextHostWidth, nextHostHeight);
} }


fIsIdling = false; fIsIdling = false;
@@ -391,6 +373,24 @@ public:
} }
} }


void setMinimumSize(const uint width, const uint height) override
{
CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fHostWindow != 0,);

fMinimumWidth = width;
fMinimumHeight = height;

XSizeHints sizeHints = {};
if (XGetNormalHints(fDisplay, fHostWindow, &sizeHints))
{
sizeHints.flags |= PMinSize;
sizeHints.min_width = static_cast<int>(width);
sizeHints.min_height = static_cast<int>(height);
XSetNormalHints(fDisplay, fHostWindow, &sizeHints);
}
}

void setSize(const uint width, const uint height, const bool forceUpdate, const bool resizeChild) override void setSize(const uint width, const uint height, const bool forceUpdate, const bool resizeChild) override
{ {
CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr,); CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr,);
@@ -404,9 +404,7 @@ public:


if (! fIsResizable) if (! fIsResizable)
{ {
XSizeHints sizeHints;
carla_zeroStruct(sizeHints);

XSizeHints sizeHints = {};
sizeHints.flags = PSize|PMinSize|PMaxSize; sizeHints.flags = PSize|PMinSize|PMaxSize;
sizeHints.width = static_cast<int>(width); sizeHints.width = static_cast<int>(width);
sizeHints.height = static_cast<int>(height); sizeHints.height = static_cast<int>(height);
@@ -464,6 +462,35 @@ public:
} }


protected: protected:
void applyHintsFromChildWindow()
{
pthread_mutex_lock(&gErrorMutex);
const XErrorHandler oldErrorHandler = XSetErrorHandler(temporaryErrorHandler);
gErrorTriggered = false;

XSizeHints sizeHints = {};
if (XGetNormalHints(fDisplay, fChildWindow, &sizeHints) && !gErrorTriggered)
{
if (fMinimumWidth != 0 && fMinimumHeight != 0)
{
sizeHints.flags |= PMinSize;
sizeHints.min_width = fMinimumWidth;
sizeHints.min_height = fMinimumHeight;
}

XSetNormalHints(fDisplay, fHostWindow, &sizeHints);
}

if (gErrorTriggered)
{
carla_stdout("Caught errors while accessing child window");
fChildWindow = 0;
}

XSetErrorHandler(oldErrorHandler);
pthread_mutex_unlock(&gErrorMutex);
}

Window getChildWindow() const Window getChildWindow() const
{ {
CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(fDisplay != nullptr, 0);
@@ -493,6 +520,8 @@ private:
bool fIsVisible; bool fIsVisible;
bool fFirstShow; bool fFirstShow;
bool fSetSizeCalledAtLeastOnce; bool fSetSizeCalledAtLeastOnce;
uint fMinimumWidth;
uint fMinimumHeight;
EventProcPtr fEventProc; EventProcPtr fEventProc;


CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(X11PluginUI) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(X11PluginUI)


+ 1
- 0
source/utils/CarlaPluginUI.hpp View File

@@ -37,6 +37,7 @@ public:
virtual void hide() = 0; virtual void hide() = 0;
virtual void focus() = 0; virtual void focus() = 0;
virtual void idle() = 0; virtual void idle() = 0;
virtual void setMinimumSize(uint with, uint height) = 0;
virtual void setSize(uint with, uint height, bool forceUpdate, bool resizeChild) = 0; virtual void setSize(uint with, uint height, bool forceUpdate, bool resizeChild) = 0;
virtual void setTitle(const char* title) = 0; virtual void setTitle(const char* title) = 0;
virtual void setChildWindow(void* ptr) = 0; virtual void setChildWindow(void* ptr) = 0;


+ 8
- 0
source/utils/CarlaVst3Utils.hpp View File

@@ -157,6 +157,14 @@ const char* tuid2str(const v3_tuid iid) noexcept


// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


struct v3_bus_mini_info {
uint16_t offset;
int32_t bus_type;
uint32_t flags;
};

// --------------------------------------------------------------------------------------------------------------------

template<class T> template<class T>
T** v3_create_class_ptr() T** v3_create_class_ptr()
{ {


Loading…
Cancel
Save