I’ve found that calling setSize() inside of an AudioProcessorEditor with a size that exceeds the screen bounds causes incorrect editor drawing / positioning. I’ve observed this with VST3 in Live - AU works properly.
I’ve got a plugin which the user can continuously resize with a corner resizer. The plugin also has an “expansion” panel for more advanced parameters, which is opened at the bottom of the plugin via a button in the UI.
The issue is - when the VST3 plugin size is close to the screen height and the user opens the expansion panel (making the plugin height greater than the available screen height), the hosting window doesn’t also expand. This results in the editor being “moved up” inside of the window, and appearing incorrectly. This doesn’t happen with AU in Live, as the host window also expands.
Here’s a video of what I’d expect to happen (AU in Live):
Here’s what happens with VST3:
What’s interesting, is if I don’t make the plugin resizable, and just size the plugin close to the screen size, then the issue doesn’t happen in VST3:
I’ve also noticed that something similar happens with VST3 in Cubase - the host window doesn’t resize. It’s less noticeable there, however, because the editor’s position stays the same. It just draws past the bottom of the host window.
Here’s the code for the demo editor used in the above videos, if helpful. Just replace the setResize… stuff in the constructor with setSize() close to the screen bounds to get the behavior in the last video.
class JuceDemoPluginAudioProcessorEditor final : public AudioProcessorEditor
{
public:
JuceDemoPluginAudioProcessorEditor (JuceDemoPluginAudioProcessor& owner)
: AudioProcessorEditor (owner)
{
wrapperLabel.setText(owner.getWrapperTypeDescription(owner.wrapperType), dontSendNotification);
addAndMakeVisible(wrapperLabel);
expandButton.setButtonText("Expand");
expandButton.setClickingTogglesState(true);
addAndMakeVisible(expandButton);
expandButton.onClick = [this]
{
if (expandButton.getToggleState())
setSize(getWidth(), std::min(getHeight() + expandHeight, maxHeight));
else
setSize(getWidth(), getHeight() - expandHeight);
};
// set resize limits for this plug-in
setResizeLimits(minWidth, minHeight, maxWidth, maxHeight);
setResizable(true, owner.wrapperType != wrapperType_AudioUnitv3);
// ... it works if you comment out the above two lines and use this instead though!
// setSize(widthCloseToScreenBounds, heightCloseToScreenBounds);
}
~JuceDemoPluginAudioProcessorEditor() override {}
//==============================================================================
void paint (Graphics& g) override
{
g.setColour(juce::Colours::darkgrey);
g.fillAll();
auto gradBounds {getNonExpandedBounds()};
g.setGradientFill(juce::ColourGradient::vertical(juce::Colours::darkred, gradBounds.getY(),
juce::Colours::darkblue, gradBounds.getBottom()));
g.fillRect(gradBounds);
}
void resized() override
{
auto bounds {getNonExpandedBounds().reduced(8)};
constexpr int w = 100;
constexpr int h = 40;
wrapperLabel.setBounds(bounds.withWidth(w).withHeight(h));
expandButton.setBounds(bounds.withSizeKeepingCentre(w, h));
}
private:
juce::Rectangle<int> getNonExpandedBounds()
{
auto bounds {getLocalBounds()};
if (expandButton.getToggleState())
bounds.removeFromBottom(expandHeight);
return bounds;
}
juce::TextButton expandButton;
juce::Label wrapperLabel;
static constexpr int minWidth = 400;
static constexpr int minHeight = 400;
static constexpr int maxWidth = 4000;
static constexpr int maxHeight = 4000;
static constexpr int expandHeight = 200;
};
Has anyone else run into this before, and have a solution? Or is this just some limit of VST3? It doesn’t seem like we get called back with the VST3 wrapper’s checkSizeConstraint()function, so the host seemingly accepts the new size, but then doesn’t actually size up it’s hosting window to it.

