Issue with AudioProcessorEditor::setScaleFactor

Tested with latest developer tip (SHA-1: 920f86eace90b4d49f91abe38abfe5a09a094a67), with Windows 10 on a Retina screen, Ableton Live 10.1.9 and in Ableton Live “Auto-Scale Plugin Window” set to off.

I am calling this right at the end of the AudioProcessorEditor constructor:

for(auto* editor : getOpenAudioEditors())
    editor->setScaleFactor(0.8f);

// Just to make sure..:
juce::MessageManager::getInstance()->callAsync([this]() {
    for(auto* editor : getOpenAudioEditors())
        editor->setScaleFactor(0.8f);
});

My plugin windows is not resized at all.

If I call the resizing code later for example when the user clicks a button, the resizing is applied.

We have no custom AffineTransform. It’s working fine on the current master.

What to do?

The issue is still there, tested with latest develop tip (SHA-1: 83b1436c6a21f82ffdc4125592836f21dbd7b1e7).

JUCE team, can you please look into this.

You should no longer use editor->setScaleFactor(), but use Desktop::setGlobalScaleFactor() now.

more information here:

Terrible idea for plugins. This would mean that ALL your instances of the same plugin would be scaled to the exact same factor.

So if you resize one Window, your other windows will now repaint at the wrong scale too. It’s a global variable.

You should create a component with an AffineTransform that scales to whatever you like and put your UI in there. A scaleable editor so to speak. Then each window can have it’s own scale.

That’s also the way I do it and my class is called “ScalablePluginEditor”… however the new JUCE recommended way is outlined in the link. The main change is that the parent editor affine transform is now reserved for scaling done by the host and that’s why editor->setScaleFactor() no longer works on windows.

Note that if you use your own component to scale, you’ll have to deal with scaling popup menus and tooltips - depending on how they are configured to pop up. But anything that’s not a child of your intermediate scaling component won’t be scaled along. There’s also stuff like the custom file chooser components and possibly dragged components. This is where the desktop way would work better, but as you wrote won’t allow to individually scale instances - but not everybody wants that.

I just noticed that our context-menus, tooltips etc. are also getting smaller when we scale our UI. This is really horrible.

We can’t use the global scale. It’s not just a “but not everybody wants that”. We don’t get to decide that. Our customers do.

I have the feeling JUCE is handled by people with no real world experience with plugins.

This extremely lazy way of using global variables, global scales etc. is simply not realistic for real world products. Sure, to quickly test if something works or for single-instance stand-alone programs you can get away with it, but not for plugins, where each instance shares the same global variables, scales etc.

It’s simply broken as it’s now. Unusably broken. The OpenGL scaling is also broken. In some apps it scales correctly, in others it doesn’t.

Not even the editor window scales correctly. It opens at 100% scale (always) and then gets “corrected” via a Timer (!) every 500ms (!). So it opens too small, and then after 500ms resizes. Which looks really amateurish and horrible. There is absolutely no reason whatsoever to NOT figure out the correct scale before even opening the window.

We’ve fixed that in the VST2 and VST3 wrappers of our fork, but that will probably never be intergrated because our code is probably not nice enough. But we’ve already had that discussion…

1 Like

Since commit 18523101 the reccomended way to scale your editor is wrap it in a top-level component which you can apply a transform to or, if you aren’t concerned with having a different scale for each instance, to use Desktop::setGlobalScaleFactor(). The rationale for these changes is to improve the reliability of the DPI handling code on Windows as before when we were simply scaling the native HWND there were some issues with OpenGL plug-ins, multi-monitor support, and behaviour differences in hosts. Using an AffineTransform for the editor smoothes out a lot of these problems but means that code that was previously using AudioProcessorEditor::setScaleFactor() will need to be updated to use one of the other scaling techniques mentioned. We’ve added an assertion in AudioProcessorEditor::editorResized() to catch this with an explanation, but if you’re running a release build then you may have missed this.

2 Likes

Thanks for the feedback. As I mentioned in the post above, these changes were made to improve the reliability of the DPI handling code on Windows - it’s a tricky problem compounded by different host behaviours, VST2/3 API differences and generally Windows scaling being a real pain (especially when you’re in a plug-in which doesn’t have control over the host process). Using a transform on the AudioProcessorEditor instead of scaling the native window has improved things somewhat but does mean that the plug-in needs to scale itself using methods other than AudioProcessorEditor::setScaleFactor() as this is now reserved for the host and user code calling it will overwrite the host scale factor. Like you said, if you want a different scale for each instance then adding the UI to a top-level Component which can be transformed is the way to go but if you are still seeing issues with this then we’d like to get them fixed.

Is this a new issue with the recent changes? Tooltips and popup menus added to the transformed component should pick up the scale of the parent.

Again, is this a new issue? From our testing, using the AudioProcessorEditor transform fixed a lot of OpenGL issues, but if you’re still seeing problems then we will take a look.

Checking the host window scale regularly is unfortunately required for VST2s which don’t have a standard way in the API of informing plug-ins of the native scale factor, and for VST3 hosts which don’t use setContentScaleFactor(), or use it incorrectly. If you have a PR which fixes the initial scale then we’ll take a look and get it merged if it behaves correctly in all hosts.

2 Likes

Turns out that we did assign a “parent” for our context-menus ourselves, because Tooltips & Slider-Popups already scale with the parent (so they become smaller / larger when resizing the window), so we wanted visual unity. It looked really broken that our context-menus stayed “full size” whereas everything else scaled.

Maybe a look-and-feel function to “double getUIScale ()” would work?

This worked fine in Cubase 10 about half a year ago, but I see that there was at least one commit again about HiDPI scaling stuff with Windows since then. Since we merge with the latest development branch, we have this new commit too now which breaks things for us.

After more digging, it turns out that is partly driver-related too. If, on the same notebook, we use the internal GPU (Intel) everything scales correctly, but if we use the dedicated Nvidia GPU, the OpenGL context-UI is scaled twice.

In Ableton Live it works fine, in Cubase it doesn’t. We also found out that Cubase apparently uses DirectX for it’s UI, so that might interfere with OpenGLs ability to set it’s own scale. It’s a shit-show. We’re now attempting to use the DirectX low-level context in the hopes that it will work better everywhere.

Yes, it behaves correctly in all hosts, because it does the exact same thing the timer does, just during the initial open. For VST2 this was very easy, for VST3 it was a bit trickier.

Here is the VST2 commit:

Here is the VST3 one:

As you can see, it’s not overly complicated. We essentially just made the timer-function into a free function and call it before the timer gets started.

2 Likes

There’s Component::getApproximateScaleFactorForComponent() which is what is used by the PopupMenu and slider popups to scale correctly - does that do what you want?

I do remember an OpenGL driver issue with Cubase, but the I think the workaround we had in place was setting the DPI awareness of the host process which is definitely not the right thing to do. In 18523101 we made some changes to set the DPI awareness of the OpenGL render threads instead and this seems to be working better, but it’s possible that the issue is driver-related and due to DirectX. We’ll try to reproduce it and look into it.

Thanks for the links to the initial scale fixes you are using, we’ve added them (with a couple of modifications) in 77787bd. There’s also a special case for Cubase 10 in there which will correct the scale sent by Cubase when the user has a non-integer scale factor set.

No. That exactly is the problem. Our GUI is wrapped in a “ScaledEditor” component that has a Transform applied to it. Now all its children are scaled as well (as expected), but the PopUps and Menus should actually have their own, independent, scale factor, so they can stay “large”.

Would it be possible to cherry-pick those into Juce 5.x too? We can’t use Juce6 right now (as we can’t legally upgrade to it until you make that available), but we would like to use your version of the fix.

Thank you reFX for providing the fix and thank you ed95 for integrating it! I’d also love to see it in Juce 5.x.

1 Like

Yep, this is on develop now.

3 Likes