Component::isShowing broken in Ableton Live

In the default mode of Ableton Live, it hides the plugin window when switching between tracks, without destroying the editor.

Since my plugin has child windows (hosted plugins), I needed to detect when that happens to hide/show the child windows - but it seems like a call to visibilityChanged is not happening, and isShowing() always returns true when polling it with a timer.

After some experimentation and help from people on the Audio Programmer Discord, I believe the internal implementation of isShowing needs to call the underlying OS API.

So I managed to get correct reporting by checking IsWindowVisible on Windows and [window isVisible] on Mac.

I believe the implementation of isShowing should also do something similar, don’t you think?

3 Likes

Thanks for reporting, we’ve made the suggested change on the develop branch. This change adds a new ComponentPeer::isShowing() member function, which is now called instead of ComponentPeer::isMinimised() in the implementation of Component::isShowing().

2 Likes

Brilliant, thank you!

It seems that this commit causes OpenGL rendering issues on Windows, specifically when using a custom OpenGLRenderer component within certain DAWs. Instead of the expected output, the screen displays only black. This behavior wasn’t present before this commit.

Below are images showing the issue in Studio One 6 on Windows 11. This example simply fills the background with a solid grey color using OpenGLHelpers::clear.

Latest JUCE 8 Develop:
juce-8-non-working

JUCE 8 Develop prior to commit 555b667:
juce-8-working

Here is the code I used to reproduce the issue:

struct TestComponent : public juce::Component, public juce::OpenGLRenderer
{
public:
	TestComponent()
	{
		m_openGLContext.setRenderer(this);
		m_openGLContext.attachTo(*getTopLevelComponent());
	}

	void newOpenGLContextCreated() override {}

	void renderOpenGL() override
	{
		juce::OpenGLHelpers::clear(juce::Colours::grey);
	}

	void openGLContextClosing() override {}


private:
	juce::OpenGLContext m_openGLContext;
};

//==============================================================================
/**
*/
class TestOpenGLAudioProcessorEditor : public juce::AudioProcessorEditor
{
public:
	TestOpenGLAudioProcessorEditor(TestOpenGLAudioProcessor& p) : AudioProcessorEditor(&p), audioProcessor(p)
	{
		addAndMakeVisible(m_glComponent);
		setSize(300, 180);
	}

	void resized() override 
	{
		m_glComponent.setBounds(getLocalBounds());
	}

private:
	TestOpenGLAudioProcessor& audioProcessor;
	TestComponent m_glComponent;

	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TestOpenGLAudioProcessorEditor)
};

Upon further testing, the issue I mentioned in my previous post is also present on macOS with VST3 and AU formats. Any subcomponent that is a juce::OpenGLRenderer won’t be displayed at all. This issue persists in the recently released JUCE 8.0.2.

Here are some screenshots from Logic Pro on macOS Sequoia running the same code as in my previous post. The intended output should be light grey.

Latest JUCE 8 Develop:
logic-pro-non-working

JUCE 8 Develop prior to commit 555b667:
logic-pro-working

i personally feel like there should be different functions for wether the thing showing is a component or a window. Component::isShowing could be about if a component is visible or not depending on if it’s in a parent that is not visible, cause that’s how it already worked. but it’s a different question if the window is even visible at all. something could be showing in the editor without the editor showing then

Before the latest change was added, this didn’t work correctly in Ableton Live. It returned true even when the parent and the entire window was not showing.

The purpose of this method is to know if the user can see your component or not, doesn’t matter what the parent hierarchy is.

1 Like

Thanks for reporting, we’ve reverted the majority of the initial change to restore the correct behaviour of OpenGL components:

The ComponentPeer::isShowing function is still in place, so it is still possible to determine whether a component is displayed on-screen by calling this function on the current peer.

1 Like