BUG? Popup Menu Background and Logic Silicon

This also happens on the example plugins, if you create a custom LookAndFeel class and set your combobox to use that L&F.

class TestLookAndFeel    : public LookAndFeel_V4
    {
    public:
        TestLookAndFeel()
        {
            const Colour newBgColour(53,53,53);
            const Colour newFgColour(220,220,220);
            setColour (PopupMenu::highlightedBackgroundColourId, newFgColour);
            setColour (PopupMenu::highlightedTextColourId, newBgColour.withAlpha(0.9f));
            setColour (PopupMenu::backgroundColourId, newBgColour.withAlpha(0.9f));
            setColour (PopupMenu::textColourId, newFgColour);
        }
        
        ~TestLookAndFeel() {}
        
        void drawPopupMenuBackground (Graphics& g, int width, int height) override
        {
            Rectangle<int> area(0, 0, width, height); //getLocalBounds().toFloat().reduced (0.5f);
            
            g.setColour(findColour (PopupMenu::backgroundColourId));
            //g.fillAll (findColour (PopupMenu::backgroundColourId));
            g.fillRoundedRectangle(area.toFloat().reduced(0.5f), 4.0f);
            //ignoreUnused (width, height);
        }
    };

I modified demoRunner to use that test LookAndFeel. It works as expected. Looks like the issue is related to Logic Pro 10.6.

I’ve investigated this a bit, and at the moment I’d agree that it’s an issue with Logic.

I’m unable to repro the issue on Logic 10.6.1 and macOS 11.1 (intel) - the issue only seems to affect ARM macs.

Standalone apps with transparent popup menus render correctly on an ARM mac. AU plugins which render incorrectly in Logic render correctly in the AudioPluginHost.

If I modify the NSViewComponentPeer to use an opaque background colour, even for transparent windows, this colour is displayed correctly. However, if the call to setBackgroundColor passes a colour which is “too transparent”, it seems to get replaced with the pinkish colour (a black background with an alpha of 0.8 renders properly, but black with an alpha of 0.7 gets replaced by the pink colour).

Thank you for looking into it. Ok, so, what can we do? Should we report this bug to Apple, and if yes, how?

Just an assumption here: maybe Logic Pro is using Metal shaders to create the transparency and/or using RGBA instead of ARGB for the pixel information.

After a bit more investigation, I’ve managed to trigger a similar issue in GarageBand 10.3 and Logic 10.6 with macOS 10.15.7 (intel).

I created a new “app” project in Xcode, then added an Audio Unit extension target to the project.

In the generated swift view controller I added the following function:

    public override func viewDidAppear() {
        for (i, alpha) in [0.7, 0.8].enumerated() {
            let w = NSWindow(contentRect: NSRect(x: 100 + 50 * i,
                                                 y: 100 + 50 * i,
                                                 width: 200,
                                                 height: 200),
                             styleMask: NSWindow.StyleMask.borderless,
                             backing: NSWindow.BackingStoreType.buffered,
                             defer: true)
            w.isOpaque = false
            w.backgroundColor = NSColor.cyan.withAlphaComponent(CGFloat(alpha))
            w.hasShadow = true
            w.level = NSWindow.Level.popUpMenu
            w.isReleasedWhenClosed = true
            w.isExcludedFromWindowsMenu = true
            w.ignoresMouseEvents = false
            w.setIsVisible(true)
            windows.append(w)
        }
    }

Here, we’re creating two cyan windows, one with an alpha of 0.7 and another with an alpha of 0.8. We set some other properties on the windows, and then make them visible.

When I open the generated AUv3 in GarageBand, I see the following:

The window with an alpha of 0.7 is displayed in pink, whereas the window with an alpha of 0.8 renders properly. It seems that any window with an alpha value which is below a certain threshold renders in pink instead, which is why JUCE’s completely clear popupmenus don’t work as expected.

Given that I can produce the above error in a completely JUCE-free app, I’m confident that this is an issue in GB/Logic’s hosting.

Interestingly, on this setup, transparent menus in a JUCE AU plugin work properly. I also tried downloading Apple’s demo AU project, and adding the extra windows to that project - again, both windows rendered in the correct colour. After a bit of debugging, I realised that the working plugins (Apple’s demo, and JUCE AUv2 plugins) were being loaded in-process, while the broken plugin was an AUv3 being loaded out-of-process. If I updated my broken AUv3 plugin to support in-process loading instead, then it also started to render correctly.

To sum up: it looks like rendering of transparent windows is broken in both Logic and GB, specifically for plugins loaded out-of-process.

It’s probably best to report the issue to apple via the offical feedback pages for GarageBand and Logic.

Edit: I tried running GarageBand on a DTK while also viewing hierarchically-grouped processes in the Activity Monitor. If I add a JUCE AU with broken popup rendering (not an AUv3, just an AU) to a track, GarageBand starts a new “AUHostingService” process, and when I remove the plugin, that process quits. This is consistent with the theory that this bug affects only plugins which are loaded out-of-process.

Could be worth emailing this guy? JUCE and macOS 11 / ARM

Seems at least he works in exactly the right team!

If you’re looking for workarounds, one possiblity might be to override getParentComponentForMenuOptions to return a pointer to your top-level component in your look and feel.

Taking the LookAndFeel example above, adjust it like so:

class TestLookAndFeel : public LookAndFeel_V4
{
public:
    explicit TestLookAndFeel (juce::Component& tlc)
        : topLevelComponent (tlc)
    {
        const Colour newBgColour (53, 53, 53);
        const Colour newFgColour (220, 220, 220);
        setColour (PopupMenu::highlightedBackgroundColourId, newFgColour);
        setColour (PopupMenu::highlightedTextColourId, newBgColour.withAlpha (0.9f));
        setColour (PopupMenu::backgroundColourId, newBgColour.withAlpha (0.9f));
        setColour (PopupMenu::textColourId, newFgColour);
    }

    juce::Component* getParentComponentForMenuOptions (const PopupMenu::Options&) override
    {
        return &topLevelComponent;
    }

    void drawPopupMenuBackground (Graphics& g, int width, int height) override
    {
        Rectangle<int> area (0, 0, width, height);

        g.setColour (findColour (PopupMenu::backgroundColourId));
        g.fillRoundedRectangle (area.toFloat().reduced (0.5f), 4.0f);
    }

    juce::Component& topLevelComponent;
};

When constructing the LookAndFeel, pass in a reference to your plugin’s AudioProcessorEditor.

Now, the popupmenu will be added to your main editor window, rather than creating a whole new floating window. It should render correctly, although the size of the popup menu will be constrained to the size of the main editor window.

I see, perhaps a bit overkill to do it just for Logic Pro. I’ve sent the bug report, hopefully, it’s going to be fixed soon. Thanks again!

That LookAndFeel mod works fine. Tested with the same project and now it renders correctly. I need to test it further on other DAWs on Silicon.

Thanks @reuk

Any feedback from Apple regarding that bug?

There is the same issue with the sliders’ popups (cf setPopupDisplayEnabled()).

I’ve sent two bug reports over the months. One through an online form, one through Feedback Assistant. No answer so far. I had a contact at Apple suggesting me to use Feedback Assistant, but he’s also not replying anymore, so not sure where to go from here.

Small update, I’ve just updated to Logic Pro 10.6.3 on Big Sur 11.3 and the bug is still there. I’ve contacted another person at Apple and the feedback I submitted was moved to macOS. This is their response:

We found the feedback, it’s on the macOS side – we already assumed that it had nothing to do with Logic. My guess would be: it happens, because Logic is built against a recent SDK, which changes some behaviors inside macOS.

Ok, I finally have a full answer and will update the ProAudio Seed Release Notes accordingly. Please check them regularly.

Windows opened by the plugin might have a subtle magenta tinting. This is security feature, not a bug. It avoids that malicious code can open a window which overlays system windows. There are a couple of ways to avoid this tinting:

  • Make the window less transparent (75% or more opacity will avoid this tinting)
  • Call -[NSWindow addChildWindow:…]. This will confine the magenta to the remote view, which spawns the child.
  • Use a standard window to obtain rounded corners without using a transparent background color.
2 Likes

Hi Markus, thank you for the update!
Reducing the transparency unfortunately is not great with rounded corners.
Regarding the other solutions, I’m not sure if JUCE can implement them directly? I hope so.

2 Likes

Well, there is another really crazy option, I haven’t even mentioned: you could use standard macOS popup menus…

1 Like

@reuk any thoughts on that?

The odd thing as mentioned before, Logic Pro is the only DAW affected by this (afaik). So, creating a workaround for just one DAW seems a bit extreme. But still…

Unfortunately, popup menus are also used in ComboBoxes to display the popup list of values, and having a native menu appearing under a custom designed widget would feel strange.

And also, It’s not just an issue with popup menus: the same magenta coloring is overlaid to rows of lists when they are dragged around, for example. And I suppose also to the semi-transparent drag image that appears when a drag gesture is started with DragAndDropContainer::startDragging()

Unfortunately I don’t think any of the suggestions would resolve the problem.

This won’t allow popup windows to have completely transparent rounded corners.

This initially seemed like a viable solution, but it seems that any part of the child window that is not on top of the parent window is still painted with a magenta background. To test, I applied this patch:

childwindow.patch (2.9 KB)

Then, I built the DSPModulePluginDemo AU and loaded it in Logic on an M1 mac. Popup menus which are not entirely contained by the editor window sill have partially magenta backgrounds.

Screenshot 2021-06-02 at 13.11.24

This is not a general solution, it only fixes the case where the desired corner radius matches that set by the OS. It doesn’t fix the issue for windows with a translucent background.

This would force the menu to use OS styling, which may not be acceptable to some developers. It would also only provide a solution for PopupMenus. This solution would not work for arbitrary floating widgets such as dragged items, tooltips and so on.

All this is to say that I still think the solution that will yield the most consistent results across platforms is to avoid opening new top-level windows entirely, and to draw widgets such as menus, tooltips, and dialogs directly into the editor window wherever possible.

2 Likes

Thank you. This is ok for small menus, but it’s awful for bigger ones. We’ll need to rewrite a few things to make them look at least decent.
I’m thinking of adding this workaround just for Logic.