When opening the PluginEditor the approximate scale factor is not up to date

For Windows with a display scale != 100 % I would like to make sure that the plugin has a reasonable size. For example, if you have a resizable plugin that takes up a large portion of the screen by default at a display scale of 100 %, you will not be able to reach the corner resizer if you use a display scale of 150 %, for example.

Therefore, when creating / opening the PluginEditor, I would like to limit its height to the current screen height. For this you need the scale factor, which can be retrieved via Component::getApproximateScaleFactorForComponent(). I noticed that immediately after opening the PluginEditor, its approximate scale factor is set to 1. Only after dragging the resizer, the approximate scale factor is updated. To reproduce this, I created a basic plugin “ResizablePlugin” (https://github.com/CppClown/ResizablePlugin2.git) with the Projucer. The plugin shows how many times resized() was called and the current approximate scale factor.

To reproduce, please work through the following steps:

  1. Clone the repo and build the plugin
  2. Move the .vst3 to the VST3 folder
  3. Change the display scale in Windows from 100 % to 150 % as follows:
    1. Open Settings
    2. Click on System
    3. Click on Display
    4. Using the first combo box in the Scale and layout section, you can change the scale to 150 %.
  4. Open the plugin in a DAW. The plugin will show Calls to resized(): 1, approximateScaleFactor = 1. I would expect an approximateScaleFactor of 1.5.
  5. Change the size of the plugin by dragging the corner resizer → The plugin will show Calls to resized(): 2, approximateScaleFactor = 1.5.

I have observed this problem in Reaper 6.80 and Cubase 12 with both VST and VST3 using JUCE 7.0.5. I have not tested other DAWs and plugin formats.

Am I misunderstanding something or is that how it’s supposed to be? What would be the right way to adjust the initial size of the plugin depending on the scaling of the screen?

Thanks in advance

I think this is the expected behaviour. There’s no interface for the host to provide a scale factor until after the PluginView is created. At the moment, we create the AudioProcessorEditor immediately after the host creates the view, and we can only assume a scale factor of 1.0 at that point.

setScaleFactor will be called on your AudioProcessorEditor when the host sets a custom scale, or if the plugin queries the display and finds that the current scale is incorrect (this normally happens if the host is older and doesn’t set any scale). You could override this function and use the requested scale when computing your editor bounds. If you do override this function, make sure to call the base class implementation so that editor scaling continues to work.

Thank you for the quick reply.

I did not know setScaleFactor() before. This is exactly the hook I was looking for. This way I can adjust the initial size of the editor according to the scaling. Thanks again!

Hi @reuk

Using setScaleFactor to trigger calculation of initial size works fine for VST, for VST3 though just before it is called the code saves the size and afterwards restores it, so any size set is lost.

Using callAsync to set the size works but unfortunately this is executed after the first paint so you get a big window then it resizes to a little window.

Any ideas?

                  auto prevEditorBounds = pluginEditor->getLocalArea (this, lastBounds);

                    {
                        const ScopedValueSetter<bool> resizingChildSetter (resizingChild, true);

                        pluginEditor->setScaleFactor (scale);
                        pluginEditor->setBounds (prevEditorBounds.withPosition (0, 0));
                    }

I asked about this back when Ed was working on this stuff, and he said it’s “needed for certain DAWs to behave correctly on Windows”. I do “manual” scaling (without affine transforms, keeping lines on integer coords to avoid blurring). This forced me to save the desired size and preface Editor::resized() with

if (desiredW != getWidth() || desiredH != getHeight())
{
    setSize (desiredW, desiredH);
    return;
}