Hi,
on OSX we encounter a strange resizing issue with a component attached to a native window. We use this method to host a plugin UI in another surrounding JUCE plugin UI. There is a AudioProcessorEditor
component and a child component is attached to the top-level component using addToDesktop(0, getTopLevelComponent()->getWindowHandle())
. Full code can be seen below.
When the top-level component is resized (using the +/- buttons), the attached component should follow but the attached component’s y-position is incorrect afterwards. This is due to the fact that JUCE internally needs to invert the coordinate system at juce_mac_NSViewComponentPeer.mm, NSViewComponentPeer::setBounds(), l.285
. The transform relies on the dimensions of the superview but this has not yet been set at this point. Hence, the resulting coordinates refer to the old parent window size.
I tried to find a fix like inverting the order of resize callbacks that are triggered in JUCE but did not succeed. My second try was to manually force a complete resize of the window hierachy with the Resize
button as a workaround. But the resizes bail out as the sizes in JUCE are the same.
So my question would be if you see a potential easy fix in JUCE or if there is a good workaround to make this work in my code? Or maybe I am wrong with my understanding how this should work?
Thanks,
Sebastian
Example Code
class NativeComponent : public Component
{
public:
void paint (Graphics& g)
{
g.fillAll (Colours::yellow);
g.setColour (Colours::black);
g.setFont (15.0f);
g.drawFittedText ("Native window!", getLocalBounds(), Justification::centred, 1);
}
};
class CompPeerTestAudioProcessorEditor : public AudioProcessorEditor, public Button::Listener
{
public:
CompPeerTestAudioProcessorEditor (CompPeerTestAudioProcessor& p) : AudioProcessorEditor (&p), processor (p)
{
setSize (400, 300);
addAndMakeVisible(btnPlus);
addAndMakeVisible(btnMinus);
addAndMakeVisible(btnResize);
btnPlus.setButtonText("+");
btnMinus.setButtonText("-");
btnResize.setButtonText("Trigger Resize");
btnPlus.addListener(this);
btnMinus.addListener(this);
btnResize.addListener(this);
addAndMakeVisible(natcomp);
}
~CompPeerTestAudioProcessorEditor() {}
//==============================================================================
void paint (Graphics& g) override
{
g.fillAll (Colours::green);
g.setColour (Colours::white);
g.setFont (15.0f);
g.drawFittedText ("Hello World!", getLocalBounds(), Justification::centred, 1);
g.drawLine(0, 100, getWidth(), 100);
g.drawLine(0, getHeight() - 100, getWidth(), getHeight() - 100);
}
void resized() override
{
btnPlus.setBounds(0, 0, 20, 20);
btnMinus.setBounds(25, 0, 20, 20);
btnResize.setBounds(50, 0, 200, 20);
natcomp.setBounds(50, 100, getWidth() - 100, getHeight() - 200);
}
void parentHierarchyChanged() override
{
natcomp.removeFromDesktop();
natcomp.addToDesktop(0, getTopLevelComponent()->getWindowHandle());
}
private:
void buttonClicked(Button* button) override
{
if (button == &btnPlus)
{
setSize(getWidth(), getHeight() + 200);
}
else if (button == &btnMinus)
{
setSize(getWidth(), getHeight() - 200);
}
else if (button == &btnResize)
{
// Force complete resize event chain by changing the size
setSize(getWidth(), getHeight() - 1);
setSize(getWidth(), getHeight() + 1);
}
}
CompPeerTestAudioProcessor& processor;
TextButton btnPlus, btnMinus, btnResize;
NativeComponent natcomp;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CompPeerTestAudioProcessorEditor)
};