Browse Source

Add support for DPI aware plug-ins on Windows

tags/2021-05-28
ed 6 years ago
parent
commit
c03469fca6
2 changed files with 185 additions and 40 deletions
  1. +90
    -22
      modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  2. +95
    -18
      modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp

+ 90
- 22
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp View File

@@ -1078,7 +1078,15 @@ public:
}
if (editorComp != nullptr)
{
editorComp->checkVisibility();
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
if (getHostType().isWavelab())
if (auto* peer = editorComp->getTopLevelComponent()->getPeer())
handleSetContentScaleFactor ((float) peer->getPlatformScaleFactor());
#endif
}
}
void createEditorComp()
@@ -1092,10 +1100,6 @@ public:
{
vstEffect.flags |= Vst2::effFlagsHasEditor;
editorComp.reset (new EditorCompWrapper (*this, *ed));
#if ! (JUCE_MAC || JUCE_IOS)
ed->setScaleFactor (editorScaleFactor);
#endif
}
else
{
@@ -1215,8 +1219,17 @@ public:
// A component to hold the AudioProcessorEditor, and cope with some housekeeping
// chores when it changes or repaints.
struct EditorCompWrapper : public Component
{
EditorCompWrapper (JuceVSTWrapper& w, AudioProcessorEditor& editor) : wrapper (w)
#if ! JUCE_MAC
, public ComponentPeer::ScaleFactorListener,
public ComponentMovementWatcher
#endif
{
EditorCompWrapper (JuceVSTWrapper& w, AudioProcessorEditor& editor)
:
#if ! JUCE_MAC
ComponentMovementWatcher (this),
#endif
wrapper (w)
{
editor.setOpaque (true);
editor.setVisible (true);
@@ -1241,6 +1254,11 @@ public:
{
deleteAllChildren(); // note that we can't use a std::unique_ptr because the editor may
// have been transferred to another parent which takes over ownership.
#if ! JUCE_MAC
for (int i = 0; i < ComponentPeer::getNumPeers(); ++i)
if (auto* peer = ComponentPeer::getPeer (i))
peer->removeScaleFactorListener (this);
#endif
}
void paint (Graphics&) override {}
@@ -1249,10 +1267,10 @@ public:
{
auto b = getSizeToContainChild();
bounds.top = 0;
bounds.left = 0;
bounds.bottom = (int16) b.getHeight();
bounds.right = (int16) b.getWidth();
bounds.top = 0;
bounds.left = 0;
bounds.bottom = (int16) b.getHeight();
bounds.right = (int16) b.getWidth();
}
void attachToHost (VstOpCodeArguments args)
@@ -1263,6 +1281,10 @@ public:
#if JUCE_WINDOWS
addToDesktop (0, args.ptr);
hostWindow = (HWND) args.ptr;
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
// workaround for plug-ins opening on an auxiliary monitor
Timer::callAfterDelay (250, [this] { updateWindowSize (false); });
#endif
#elif JUCE_LINUX
addToDesktop (0, args.ptr);
hostWindow = (Window) args.ptr;
@@ -1302,6 +1324,32 @@ public:
return dynamic_cast<AudioProcessorEditor*> (getChildComponent(0));
}
float getNativeEditorScaleFactor() const noexcept { return nativeScaleFactor; }
#if ! JUCE_MAC
void componentMovedOrResized (bool, bool) override {}
void componentPeerChanged() override
{
if (auto* peer = getTopLevelComponent()->getPeer())
peer->addScaleFactorListener (this);
}
void componentVisibilityChanged() override
{
if (auto* peer = getTopLevelComponent()->getPeer())
nativeScaleFactorChanged (peer->getPlatformScaleFactor());
}
void nativeScaleFactorChanged (double newScaleFactor) override
{
nativeScaleFactor = (float) newScaleFactor;
if (getHostType().isBitwigStudio())
updateWindowSize (true);
}
#endif
void resized() override
{
if (auto* ed = getEditorComp())
@@ -1359,7 +1407,9 @@ public:
shouldResizeEditor = true;
#else
ignoreUnused (resizeEditor);
XResizeWindow (display.display, (Window) getWindowHandle(), pos.getWidth(), pos.getHeight());
XResizeWindow (display.display, (Window) getWindowHandle(),
static_cast<unsigned int> (roundToInt (pos.getWidth() * nativeScaleFactor)),
static_cast<unsigned int> (roundToInt (pos.getHeight() * nativeScaleFactor)));
#endif
#if JUCE_MAC
@@ -1380,7 +1430,9 @@ public:
if (status == (pointer_sized_int) 1 || getHostType().isAbletonLive())
{
isInSizeWindow = true;
sizeWasSuccessful = (host (wrapper.getAEffect(), Vst2::audioMasterSizeWindow, newWidth, newHeight, 0, 0) != 0);
sizeWasSuccessful = (host (wrapper.getAEffect(), Vst2::audioMasterSizeWindow,
roundToInt (newWidth * nativeScaleFactor),
roundToInt (newHeight * nativeScaleFactor), 0, 0) != 0);
isInSizeWindow = false;
}
}
@@ -1478,6 +1530,8 @@ public:
bool isInSizeWindow = false;
bool shouldResizeEditor = true;
float nativeScaleFactor = 1.0f;
#if JUCE_MAC
void* hostWindow = {};
#elif JUCE_LINUX
@@ -2115,21 +2169,36 @@ private:
pointer_sized_int handleSetContentScaleFactor (float scale)
{
if (editorScaleFactor != scale)
#if ! JUCE_MAC
if (editorComp != nullptr)
{
editorScaleFactor = scale;
#if ! (JUCE_MAC || JUCE_IOS)
if (editorComp != nullptr)
#if JUCE_WINDOWS && ! JUCE_WIN_PER_MONITOR_DPI_AWARE
if (auto* ed = editorComp->getEditorComp())
{
if (auto* ed = editorComp->getEditorComp())
ed->setScaleFactor (editorScaleFactor);
ed->setScaleFactor (scale);
editorComp->updateWindowSize (true);
}
#else
if (! approximatelyEqual (scale, (float) editorComp->getNativeEditorScaleFactor()))
{
editorComp->nativeScaleFactorChanged ((double) scale);
if (editorComp != nullptr)
editorComp->updateWindowSize (true);
#if JUCE_LINUX
MessageManager::callAsync ([this] { if (editorComp != nullptr) editorComp->updateWindowSize (true); });
#else
editorComp->updateWindowSize (true);
#endif
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
if (getHostType().isStudioOne())
Timer::callAfterDelay (100, [this] { if (editorComp != nullptr) editorComp->updateWindowSize (false); });
#endif
}
#endif
}
#else
ignoreUnused (scale);
#endif
return 1;
}
@@ -2185,7 +2254,6 @@ private:
Vst2::ERect editorBounds;
MidiBuffer midiEvents;
VSTMidiEventList outgoingEvents;
float editorScaleFactor = 1.0f;
LegacyAudioParametersWrapper juceParameters;


+ 95
- 18
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -883,7 +883,10 @@ private:
if (component != nullptr)
{
component->setSize (rect.getWidth(), rect.getHeight());
auto scale = component->getNativeEditorScaleFactor();
component->setSize (roundToInt (rect.getWidth() / scale),
roundToInt (rect.getHeight() / scale));
if (auto* peer = component->getPeer())
peer->updateBounds();
@@ -900,7 +903,12 @@ private:
{
if (size != nullptr && component != nullptr)
{
*size = ViewRect (0, 0, component->getWidth(), component->getHeight());
auto scale = component->getNativeEditorScaleFactor();
*size = ViewRect (0, 0,
roundToInt (component->getWidth() * scale),
roundToInt (component->getHeight() * scale));
return kResultTrue;
}
@@ -923,16 +931,21 @@ private:
if (auto* editor = component->pluginEditor.get())
{
// checkSizeConstraint
auto juceRect = editor->getLocalArea (component.get(), Rectangle<int>::leftTopRightBottom (rectToCheck->left, rectToCheck->top,
rectToCheck->right, rectToCheck->bottom));
auto scale = component->getNativeEditorScaleFactor();
auto scaledRect = (Rectangle<int>::leftTopRightBottom (rectToCheck->left, rectToCheck->top,
rectToCheck->right, rectToCheck->bottom).toFloat() / scale).toNearestInt();
auto juceRect = editor->getLocalArea (component.get(), scaledRect);
if (auto* constrainer = editor->getConstrainer())
{
Rectangle<int> limits (0, 0, constrainer->getMaximumWidth(), constrainer->getMaximumHeight());
constrainer->checkBounds (juceRect, editor->getBounds(), limits, false, false, false, false);
juceRect = component->getLocalArea (editor, juceRect);
rectToCheck->right = rectToCheck->left + juceRect.getWidth();
rectToCheck->bottom = rectToCheck->top + juceRect.getHeight();
rectToCheck->right = rectToCheck->left + roundToInt (juceRect.getWidth() * scale);
rectToCheck->bottom = rectToCheck->top + roundToInt (juceRect.getHeight() * scale);
}
}
@@ -945,17 +958,22 @@ private:
tresult PLUGIN_API setContentScaleFactor (Steinberg::IPlugViewContentScaleSupport::ScaleFactor factor) override
{
#if (JUCE_MAC || JUCE_IOS)
ignoreUnused (factor);
#else
if (auto* editor = component->pluginEditor.get())
{
editor->setScaleFactor (factor);
return kResultTrue;
}
#endif
#if ! JUCE_MAC
#if JUCE_WINDOWS && ! JUCE_WIN_PER_MONITOR_DPI_AWARE
if (auto* ed = component->pluginEditor.get())
ed->setScaleFactor ((float) factor);
#else
if (! approximatelyEqual (component->getNativeEditorScaleFactor(), (float) factor))
component->nativeScaleFactorChanged ((double) factor);
#endif
component->resizeHostWindow();
return kResultTrue;
#else
ignoreUnused (factor);
return kResultFalse;
#endif
}
private:
@@ -970,10 +988,18 @@ private:
//==============================================================================
struct ContentWrapperComponent : public Component
#if ! JUCE_MAC
, public ComponentPeer::ScaleFactorListener,
public ComponentMovementWatcher
#endif
{
ContentWrapperComponent (JuceVST3Editor& editor, AudioProcessor& plugin)
: pluginEditor (plugin.createEditorIfNeeded()),
owner (editor)
:
#if ! JUCE_MAC
ComponentMovementWatcher (this),
#endif
pluginEditor (plugin.createEditorIfNeeded()),
owner (editor)
{
setOpaque (true);
setBroughtToFrontOnMouseClick (true);
@@ -1004,6 +1030,12 @@ private:
PopupMenu::dismissAllActiveMenus();
pluginEditor->processor.editorBeingDeleted (pluginEditor.get());
}
#if ! JUCE_MAC
for (int i = 0; i < ComponentPeer::getNumPeers(); ++i)
if (auto* p = ComponentPeer::getPeer (i))
p->removeScaleFactorListener (this);
#endif
}
void paint (Graphics& g) override
@@ -1084,7 +1116,7 @@ private:
if (owner.plugFrame != nullptr)
{
ViewRect newSize (0, 0, w, h);
ViewRect newSize (0, 0, roundToInt (w * nativeScaleFactor), roundToInt (h * nativeScaleFactor));
isResizingParentToFitChild = true;
owner.plugFrame->resizeView (&owner, &newSize);
isResizingParentToFitChild = false;
@@ -1099,6 +1131,49 @@ private:
}
}
float getNativeEditorScaleFactor() const noexcept { return nativeScaleFactor; }
#if ! JUCE_MAC
void componentMovedOrResized (bool, bool) override {}
void componentPeerChanged() override
{
if (auto* peer = getTopLevelComponent()->getPeer())
peer->addScaleFactorListener (this);
}
void componentVisibilityChanged() override
{
if (auto* peer = getTopLevelComponent()->getPeer())
nativeScaleFactor = (float) peer->getPlatformScaleFactor();
}
void nativeScaleFactorChanged (double newScaleFactor) override
{
nativeScaleFactor = (float) newScaleFactor;
auto host = getHostType();
if (host.isWavelab())
{
Timer::callAfterDelay (250, [this] {
if (auto* peer = getPeer())
{
peer->updateBounds();
repaint();
}
resizeHostWindow();
});
}
else if (host.isBitwigStudio())
{
resizeHostWindow();
setTopLeftPosition (0, 0);
}
}
#endif
std::unique_ptr<AudioProcessorEditor> pluginEditor;
private:
@@ -1108,6 +1183,8 @@ private:
bool isResizingChildToFitParent = false;
bool isResizingParentToFitChild = false;
float nativeScaleFactor = 1.0f;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent)
};


Loading…
Cancel
Save