From 69e0727ffd0ac2a213d481dbac2b984b881d56c7 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 29 Sep 2022 13:31:13 +0100 Subject: [PATCH] VST3 Client: Attempt to preserve scale set by host --- .../VST3/juce_VST3_Wrapper.cpp | 77 ++++++++++++------- modules/juce_core/misc/juce_Functional.h | 6 +- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp index 7d3f7ce83c..5b8fd00727 100644 --- a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp @@ -1786,8 +1786,7 @@ private: // constructor, we don't have a host plugFrame, so // ContentWrapperComponent::resizeHostWindow() won't do anything, and the content // wrapper component will be left at the wrong size. - if (! approximatelyEqual (editorScaleFactor, owner->lastScaleFactorReceived)) - setContentScaleFactor (owner->lastScaleFactorReceived); + applyScaleFactor (StoredScaleFactor{}.withInternal (owner->lastScaleFactorReceived)); // Check the host scale factor *before* calling addToDesktop, so that the initial // window size during addToDesktop is correct for the current platform scale factor. @@ -1990,35 +1989,28 @@ private: return kResultFalse; } - tresult PLUGIN_API setContentScaleFactor (Steinberg::IPlugViewContentScaleSupport::ScaleFactor factor) override + tresult PLUGIN_API setContentScaleFactor (const Steinberg::IPlugViewContentScaleSupport::ScaleFactor factor) override { #if ! JUCE_MAC - if (! approximatelyEqual ((float) factor, editorScaleFactor)) + const auto scaleToApply = [&] { #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE // Cubase 10 only sends integer scale factors, so correct this for fractional scales - if (getHostType().type == PluginHostType::SteinbergCubase10) - { - auto hostWindowScale = (Steinberg::IPlugViewContentScaleSupport::ScaleFactor) getScaleFactorForWindow ((HWND) systemWindow); + if (getHostType().type != PluginHostType::SteinbergCubase10) + return factor; - if (hostWindowScale > 0.0 && ! approximatelyEqual (factor, hostWindowScale)) - factor = hostWindowScale; - } - #endif + const auto hostWindowScale = (Steinberg::IPlugViewContentScaleSupport::ScaleFactor) getScaleFactorForWindow (static_cast (systemWindow)); - editorScaleFactor = (float) factor; + if (hostWindowScale <= 0.0 || approximatelyEqual (factor, hostWindowScale)) + return factor; - if (owner != nullptr) - owner->lastScaleFactorReceived = editorScaleFactor; + return hostWindowScale; + #else + return factor; + #endif + }(); - if (component != nullptr) - { - #if JUCE_LINUX || JUCE_BSD - const MessageManagerLock mmLock; - #endif - component->setEditorScaleFactor (editorScaleFactor); - } - } + applyScaleFactor (scaleFactor.withHost (scaleToApply)); return kResultTrue; #else @@ -2103,7 +2095,7 @@ private: pluginEditor->setHostContext (editorHostContext.get()); #if ! JUCE_MAC - pluginEditor->setScaleFactor (owner.editorScaleFactor); + pluginEditor->setScaleFactor (owner.scaleFactor.get()); #endif addAndMakeVisible (pluginEditor.get()); @@ -2234,10 +2226,10 @@ private: #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE void checkHostWindowScaleFactor() { - auto hostWindowScale = (float) getScaleFactorForWindow ((HWND) owner.systemWindow); + const auto estimatedScale = (float) getScaleFactorForWindow (static_cast (owner.systemWindow)); - if (hostWindowScale > 0.0 && ! approximatelyEqual (hostWindowScale, owner.editorScaleFactor)) - owner.setContentScaleFactor (hostWindowScale); + if (estimatedScale > 0.0) + owner.applyScaleFactor (owner.scaleFactor.withInternal (estimatedScale)); } void timerCallback() override @@ -2321,7 +2313,38 @@ private: std::unique_ptr cubase10Workaround; #else - float editorScaleFactor = 1.0f; + class StoredScaleFactor + { + public: + StoredScaleFactor withHost (float x) const { return withMember (*this, &StoredScaleFactor::host, x); } + StoredScaleFactor withInternal (float x) const { return withMember (*this, &StoredScaleFactor::internal, x); } + float get() const { return host.value_or (internal); } + + private: + std::optional host; + float internal = 1.0f; + }; + + void applyScaleFactor (const StoredScaleFactor newFactor) + { + const auto previous = std::exchange (scaleFactor, newFactor).get(); + + if (previous == scaleFactor.get()) + return; + + if (owner != nullptr) + owner->lastScaleFactorReceived = scaleFactor.get(); + + if (component != nullptr) + { + #if JUCE_LINUX || JUCE_BSD + const MessageManagerLock mmLock; + #endif + component->setEditorScaleFactor (scaleFactor.get()); + } + } + + StoredScaleFactor scaleFactor; #if JUCE_WINDOWS WindowsHooks hooks; diff --git a/modules/juce_core/misc/juce_Functional.h b/modules/juce_core/misc/juce_Functional.h index 858c478af8..b458c4811a 100644 --- a/modules/juce_core/misc/juce_Functional.h +++ b/modules/juce_core/misc/juce_Functional.h @@ -79,10 +79,10 @@ template using DisableIfSameOrDerived = std::enable_if_t>>; /** Copies an object, sets one of the copy's members to the specified value, and then returns the copy. */ -template -Object withMember (Object copy, Member OtherObject::* member, Member&& value) +template +Object withMember (Object copy, Member OtherObject::* member, Other&& value) { - copy.*member = std::forward (value); + copy.*member = std::forward (value); return copy; }