mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Plugin Client: Change scaling mechanism on Linux/Windows plugins
This commit is contained in:
parent
b4c28db765
commit
fcf1971122
4 changed files with 361 additions and 340 deletions
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace juce::detail
|
||||
{
|
||||
|
||||
/** Keeps track of scale factors specified by the host and/or queried by the
|
||||
the plugin.
|
||||
*/
|
||||
class StoredScaleFactor
|
||||
{
|
||||
public:
|
||||
/** Sets a scale factor that originated from the host.
|
||||
This scale will take precedence over other scale factors.
|
||||
*/
|
||||
StoredScaleFactor withHost (float x) const { return withMember (*this, &StoredScaleFactor::host, x); }
|
||||
|
||||
/** Sets a scale factor that originated from the plugin.
|
||||
This scale will only be used if there's no host-provided scale.
|
||||
Defaults to 1.0f.
|
||||
*/
|
||||
StoredScaleFactor withInternal (float x) const { return withMember (*this, &StoredScaleFactor::internal, x); }
|
||||
|
||||
/** Returns the host-provided scale, if any, or the internal scale otherwise. */
|
||||
float get() const { return host.value_or (internal); }
|
||||
|
||||
/** Returns true if this object holds a host-originated scale, or false otherwise. */
|
||||
bool isHostScale() const { return host.has_value(); }
|
||||
|
||||
private:
|
||||
std::optional<float> host;
|
||||
float internal = 1.0f;
|
||||
};
|
||||
|
||||
class PluginScaleFactorManagerListener
|
||||
{
|
||||
public:
|
||||
virtual ~PluginScaleFactorManagerListener() = default;
|
||||
virtual void peerBoundsDidUpdate() = 0;
|
||||
};
|
||||
|
||||
class PluginScaleFactorManager : private Timer,
|
||||
private ComponentListener
|
||||
{
|
||||
public:
|
||||
~PluginScaleFactorManager() override
|
||||
{
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
void startObserving (Component& comp)
|
||||
{
|
||||
observed = ∁
|
||||
observed->addComponentListener (this);
|
||||
applyScaleFactor (scale);
|
||||
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
if (! scale.isHostScale())
|
||||
startTimer (500);
|
||||
#endif
|
||||
}
|
||||
|
||||
void stopObserving ([[maybe_unused]] Component& comp)
|
||||
{
|
||||
stopTimer();
|
||||
jassert (&comp == observed.getComponent());
|
||||
observed->removeComponentListener (this);
|
||||
observed = nullptr;
|
||||
}
|
||||
|
||||
void addListener (PluginScaleFactorManagerListener& l)
|
||||
{
|
||||
listeners.add (&l);
|
||||
}
|
||||
|
||||
void removeListener (PluginScaleFactorManagerListener& l)
|
||||
{
|
||||
listeners.remove (&l);
|
||||
}
|
||||
|
||||
void setHostScale (float x)
|
||||
{
|
||||
stopTimer();
|
||||
applyScaleFactor (scale.withHost (x));
|
||||
}
|
||||
|
||||
std::optional<float> getHostScale() const
|
||||
{
|
||||
return scale.isHostScale() ? std::optional (scale.get()) : std::nullopt;
|
||||
}
|
||||
|
||||
Rectangle<int> convertToHostBounds (Rectangle<float> pluginRect) const
|
||||
{
|
||||
jassert (observed != nullptr);
|
||||
return (observed->localAreaToGlobal (pluginRect) * getPlatformAndDesktopScale()).withZeroOrigin().toNearestIntEdges();
|
||||
}
|
||||
|
||||
Rectangle<float> convertFromHostBounds (Rectangle<int> hostViewRect) const
|
||||
{
|
||||
jassert (observed != nullptr);
|
||||
return observed->getLocalArea (nullptr, hostViewRect.toFloat() / getPlatformAndDesktopScale()).withZeroOrigin();
|
||||
}
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
static double getScaleFactorForWindow (HWND h)
|
||||
{
|
||||
return (double) GetDpiForWindow (h) / USER_DEFAULT_SCREEN_DPI;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
void componentParentHierarchyChanged (Component&) override
|
||||
{
|
||||
if (auto* peer = observed->getPeer())
|
||||
peer->setCustomPlatformScaleFactor (getHostScale());
|
||||
}
|
||||
|
||||
float getScaleFactorForWindow() const
|
||||
{
|
||||
if (auto* comp = observed.getComponent())
|
||||
if (auto* peer = comp->getPeer())
|
||||
return (float) peer->getPlatformScaleFactor();
|
||||
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
if (const auto estimatedScale = getScaleFactorForWindow(); estimatedScale > 0.0f)
|
||||
applyScaleFactor (scale.withInternal (estimatedScale));
|
||||
}
|
||||
|
||||
void applyScaleFactor (StoredScaleFactor newFactor)
|
||||
{
|
||||
const auto previous = std::exchange (scale, newFactor).get();
|
||||
const auto current = scale.get();
|
||||
const auto scalesEqual = approximatelyEqual (current, previous);
|
||||
|
||||
if (observed == nullptr)
|
||||
return;
|
||||
|
||||
if (scale.isHostScale())
|
||||
if (auto* peer = observed->getPeer())
|
||||
peer->setCustomPlatformScaleFactor (current);
|
||||
|
||||
if (scalesEqual)
|
||||
return;
|
||||
|
||||
#if JUCE_LINUX || JUCE_BSD
|
||||
const MessageManagerLock mmLock;
|
||||
#endif
|
||||
|
||||
if (auto* peer = observed->getPeer())
|
||||
{
|
||||
peer->updateBounds();
|
||||
listeners.call ([] (auto& l) { l.peerBoundsDidUpdate(); });
|
||||
}
|
||||
}
|
||||
|
||||
float getPlatformAndDesktopScale() const
|
||||
{
|
||||
jassert (observed != nullptr);
|
||||
return (observed->getDesktopScaleFactor() * std::invoke ([&]
|
||||
{
|
||||
if (auto* peer = observed->getPeer())
|
||||
return (float) peer->getPlatformScaleFactor();
|
||||
|
||||
return scale.get();
|
||||
}));
|
||||
}
|
||||
|
||||
ListenerList<PluginScaleFactorManagerListener> listeners;
|
||||
Component::SafePointer<Component> observed;
|
||||
StoredScaleFactor scale;
|
||||
};
|
||||
|
||||
} // namespace juce::detail
|
||||
|
|
@ -49,6 +49,7 @@
|
|||
#include <juce_audio_plugin_client/juce_audio_plugin_client.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_CheckSettingMacros.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_PluginUtilities.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_PluginScaleFactorUtilities.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_LinuxMessageThread.h>
|
||||
|
||||
#include <juce_audio_processors_headless/utilities/juce_FlagCache.h>
|
||||
|
|
@ -769,6 +770,8 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
detail::PluginScaleFactorManager& getScaleManager() { return scaleManager; }
|
||||
|
||||
private:
|
||||
void audioProcessorParameterChanged (AudioProcessor*, int, float) override {}
|
||||
|
||||
|
|
@ -800,6 +803,8 @@ private:
|
|||
|
||||
ScopedJuceInitialiser_GUI scopedJuceInitialiser;
|
||||
|
||||
detail::PluginScaleFactorManager scaleManager;
|
||||
|
||||
#if JUCE_LINUX || JUCE_BSD
|
||||
SharedResourcePointer<detail::MessageThread> messageThread;
|
||||
#endif
|
||||
|
|
@ -1509,7 +1514,7 @@ LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor (uint32_t index)
|
|||
return &descriptor;
|
||||
}
|
||||
|
||||
static Optional<float> findScaleFactor (const LV2_URID_Map* symap, const LV2_Options_Option* options)
|
||||
static std::optional<float> findScaleFactor (const LV2_URID_Map* symap, const LV2_Options_Option* options)
|
||||
{
|
||||
if (options == nullptr || symap == nullptr)
|
||||
return {};
|
||||
|
|
@ -1521,7 +1526,7 @@ static Optional<float> findScaleFactor (const LV2_URID_Map* symap, const LV2_Opt
|
|||
}
|
||||
|
||||
class LV2UIInstance final : private Component,
|
||||
private ComponentListener
|
||||
private detail::PluginScaleFactorManagerListener
|
||||
{
|
||||
public:
|
||||
LV2UIInstance (const char*,
|
||||
|
|
@ -1533,14 +1538,13 @@ public:
|
|||
LV2UI_Widget parentIn,
|
||||
const LV2_URID_Map* symapIn,
|
||||
const LV2UI_Resize* resizeFeatureIn,
|
||||
Optional<float> scaleFactorIn)
|
||||
std::optional<float> scaleFactorIn)
|
||||
: writeFunction (writeFunctionIn),
|
||||
controller (controllerIn),
|
||||
plugin (pluginIn),
|
||||
parent (parentIn),
|
||||
symap (symapIn),
|
||||
resizeFeature (resizeFeatureIn),
|
||||
scaleFactor (scaleFactorIn),
|
||||
editor (plugin->createEditor())
|
||||
{
|
||||
jassert (plugin != nullptr);
|
||||
|
|
@ -1550,6 +1554,9 @@ public:
|
|||
if (editor == nullptr)
|
||||
return;
|
||||
|
||||
plugin->getScaleManager().addListener (*this);
|
||||
plugin->getScaleManager().startObserving (*this);
|
||||
|
||||
const auto bounds = getSizeToContainChild();
|
||||
setSize (bounds.getWidth(), bounds.getHeight());
|
||||
|
||||
|
|
@ -1560,18 +1567,22 @@ public:
|
|||
setVisible (false);
|
||||
removeFromDesktop();
|
||||
addToDesktop (detail::PluginUtilities::getDesktopFlags (editor.get()), parent);
|
||||
editor->addComponentListener (this);
|
||||
|
||||
*widget = getWindowHandle();
|
||||
|
||||
setVisible (true);
|
||||
|
||||
editor->setScaleFactor (getScaleFactor());
|
||||
if (scaleFactorIn.has_value())
|
||||
plugin->getScaleManager().setHostScale (*scaleFactorIn);
|
||||
|
||||
requestResize();
|
||||
}
|
||||
|
||||
~LV2UIInstance() override
|
||||
{
|
||||
plugin->getScaleManager().stopObserving (*this);
|
||||
plugin->getScaleManager().removeListener (*this);
|
||||
|
||||
plugin->editorBeingDeleted (editor.get());
|
||||
}
|
||||
|
||||
|
|
@ -1582,8 +1593,17 @@ public:
|
|||
// Called when the host requests a resize
|
||||
int resize (int width, int height)
|
||||
{
|
||||
const ScopedValueSetter<bool> scope (hostRequestedResize, true);
|
||||
setSize (width, height);
|
||||
const ScopedValueSetter scope (resizingChild, true);
|
||||
|
||||
if (editor == nullptr)
|
||||
return 0;
|
||||
|
||||
const auto logicalBounds = plugin->getScaleManager().convertFromHostBounds ({ width, height }).toNearestIntEdges();
|
||||
editor->setBoundsConstrained (logicalBounds.withZeroOrigin());
|
||||
|
||||
const auto bounds = getSizeToContainChild();
|
||||
setSize (bounds.getWidth(), bounds.getHeight());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1595,34 +1615,34 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
const ScopedValueSetter<bool> scope (hostRequestedResize, true);
|
||||
|
||||
if (editor != nullptr)
|
||||
{
|
||||
const auto localArea = editor->getLocalArea (this, getLocalBounds());
|
||||
editor->setBoundsConstrained ({ localArea.getWidth(), localArea.getHeight() });
|
||||
}
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override { g.fillAll (Colours::black); }
|
||||
|
||||
void parentSizeChanged() override
|
||||
{
|
||||
if (editor == nullptr)
|
||||
return;
|
||||
|
||||
requestResize();
|
||||
editor->repaint();
|
||||
}
|
||||
|
||||
uint32_t getOptions (LV2_Options_Option* options)
|
||||
{
|
||||
const auto scaleFactorUrid = symap->map (symap->handle, LV2_UI__scaleFactor);
|
||||
const auto floatUrid = symap->map (symap->handle, LV2_ATOM__Float);;
|
||||
const auto floatUrid = symap->map (symap->handle, LV2_ATOM__Float);
|
||||
|
||||
for (auto* opt = options; opt->key != 0; ++opt)
|
||||
{
|
||||
if (opt->context != LV2_OPTIONS_INSTANCE || opt->subject != 0 || opt->key != scaleFactorUrid)
|
||||
continue;
|
||||
|
||||
if (scaleFactor.hasValue())
|
||||
if (const auto optionalHostScale = plugin->getScaleManager().getHostScale())
|
||||
{
|
||||
hostScale = *optionalHostScale;
|
||||
|
||||
opt->type = floatUrid;
|
||||
opt->size = sizeof (float);
|
||||
opt->value = &(*scaleFactor);
|
||||
opt->value = &hostScale;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1632,7 +1652,7 @@ public:
|
|||
uint32_t setOptions (const LV2_Options_Option* options)
|
||||
{
|
||||
const auto scaleFactorUrid = symap->map (symap->handle, LV2_UI__scaleFactor);
|
||||
const auto floatUrid = symap->map (symap->handle, LV2_ATOM__Float);;
|
||||
const auto floatUrid = symap->map (symap->handle, LV2_ATOM__Float);
|
||||
|
||||
for (auto* opt = options; opt->key != 0; ++opt)
|
||||
{
|
||||
|
|
@ -1645,20 +1665,13 @@ public:
|
|||
continue;
|
||||
}
|
||||
|
||||
scaleFactor = *static_cast<const float*> (opt->value);
|
||||
updateScale();
|
||||
plugin->getScaleManager().setHostScale (*static_cast<const float*> (opt->value));
|
||||
}
|
||||
|
||||
return LV2_OPTIONS_SUCCESS;
|
||||
}
|
||||
|
||||
private:
|
||||
void updateScale()
|
||||
{
|
||||
editor->setScaleFactor (getScaleFactor());
|
||||
requestResize();
|
||||
}
|
||||
|
||||
Rectangle<int> getSizeToContainChild() const
|
||||
{
|
||||
if (editor != nullptr)
|
||||
|
|
@ -1667,15 +1680,17 @@ private:
|
|||
return {};
|
||||
}
|
||||
|
||||
float getScaleFactor() const noexcept
|
||||
void peerBoundsDidUpdate() override
|
||||
{
|
||||
return scaleFactor.hasValue() ? *scaleFactor : 1.0f;
|
||||
requestResize();
|
||||
}
|
||||
|
||||
void componentMovedOrResized (Component&, bool, bool wasResized) override
|
||||
void childBoundsChanged (Component*) override
|
||||
{
|
||||
if (! hostRequestedResize && wasResized)
|
||||
requestResize();
|
||||
if (resizingChild)
|
||||
return;
|
||||
|
||||
requestResize();
|
||||
}
|
||||
|
||||
void write (uint32_t portIndex, uint32_t bufferSize, uint32_t portProtocol, const void* data)
|
||||
|
|
@ -1688,16 +1703,19 @@ private:
|
|||
if (editor == nullptr)
|
||||
return;
|
||||
|
||||
const auto bounds = getSizeToContainChild();
|
||||
|
||||
if (resizeFeature == nullptr)
|
||||
return;
|
||||
|
||||
if (auto* fn = resizeFeature->ui_resize)
|
||||
fn (resizeFeature->handle, bounds.getWidth(), bounds.getHeight());
|
||||
const auto logicalBounds = getSizeToContainChild();
|
||||
const auto physicalBounds = plugin->getScaleManager().convertToHostBounds (logicalBounds.toFloat());
|
||||
|
||||
setSize (bounds.getWidth(), bounds.getHeight());
|
||||
repaint();
|
||||
if (auto* fn = resizeFeature->ui_resize)
|
||||
fn (resizeFeature->handle, physicalBounds.getWidth(), physicalBounds.getHeight());
|
||||
|
||||
setBounds (logicalBounds.withZeroOrigin());
|
||||
|
||||
if (auto* peer = getPeer())
|
||||
peer->updateBounds();
|
||||
}
|
||||
|
||||
#if JUCE_LINUX || JUCE_BSD
|
||||
|
|
@ -1710,9 +1728,9 @@ private:
|
|||
LV2UI_Widget parent;
|
||||
const LV2_URID_Map* symap = nullptr;
|
||||
const LV2UI_Resize* resizeFeature = nullptr;
|
||||
Optional<float> scaleFactor;
|
||||
std::unique_ptr<AudioProcessorEditor> editor;
|
||||
bool hostRequestedResize = false;
|
||||
float hostScale = 0.0f;
|
||||
bool resizingChild = false;
|
||||
|
||||
JUCE_LEAK_DETECTOR (LV2UIInstance)
|
||||
};
|
||||
|
|
@ -1757,7 +1775,7 @@ LV2_SYMBOL_EXPORT const LV2UI_Descriptor* lv2ui_descriptor (uint32_t index)
|
|||
|
||||
auto* resizeFeature = findMatchingFeatureData<const LV2UI_Resize*> (features, LV2_UI__resize);
|
||||
|
||||
const auto* symap = findMatchingFeatureData<const LV2_URID_Map*> (features, LV2_URID__map);
|
||||
const auto* symap = findMatchingFeatureData<const LV2_URID_Map*> (features, LV2_URID__map);
|
||||
const auto scaleFactor = findScaleFactor (symap, findMatchingFeatureData<const LV2_Options_Option*> (features, LV2_OPTIONS__options));
|
||||
|
||||
return new LV2UIInstance { pluginUri,
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
|||
#define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1
|
||||
|
||||
#include <juce_audio_plugin_client/detail/juce_PluginUtilities.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_PluginScaleFactorUtilities.h>
|
||||
|
||||
using namespace juce;
|
||||
|
||||
|
|
@ -131,13 +132,6 @@ using namespace juce;
|
|||
class JuceVSTWrapper;
|
||||
static bool recursionCheck = false;
|
||||
|
||||
namespace juce
|
||||
{
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
JUCE_API double getScaleFactorForWindow (HWND);
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_WINDOWS
|
||||
|
||||
|
|
@ -348,7 +342,7 @@ public:
|
|||
#if JucePlugin_IsSynth
|
||||
vstEffect.flags |= Vst2::effFlagsIsSynth;
|
||||
#else
|
||||
if (processor->getTailLengthSeconds() == 0.0)
|
||||
if (approximatelyEqual (processor->getTailLengthSeconds(), 0.0))
|
||||
vstEffect.flags |= Vst2::effFlagsNoSoundInStop;
|
||||
#endif
|
||||
|
||||
|
|
@ -823,7 +817,7 @@ public:
|
|||
if (auto* ed = processor->createEditorIfNeeded())
|
||||
{
|
||||
setHasEditorFlag (true);
|
||||
editorComp.reset (new EditorCompWrapper (*this, *ed, editorScaleFactor));
|
||||
editorComp.reset (new EditorCompWrapper (*this, *ed));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -928,18 +922,13 @@ public:
|
|||
//==============================================================================
|
||||
// A component to hold the AudioProcessorEditor, and cope with some housekeeping
|
||||
// chores when it changes or repaints.
|
||||
struct EditorCompWrapper final : public Component
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
, public Timer
|
||||
#endif
|
||||
struct EditorCompWrapper final : public Component,
|
||||
private detail::PluginScaleFactorManagerListener
|
||||
{
|
||||
EditorCompWrapper (JuceVSTWrapper& w, AudioProcessorEditor& editor, [[maybe_unused]] float initialScale)
|
||||
EditorCompWrapper (JuceVSTWrapper& w, AudioProcessorEditor& editor)
|
||||
: wrapper (w)
|
||||
{
|
||||
editor.setOpaque (true);
|
||||
#if ! JUCE_MAC
|
||||
editor.setScaleFactor (initialScale);
|
||||
#endif
|
||||
addAndMakeVisible (editor);
|
||||
|
||||
auto editorBounds = getSizeToContainChild();
|
||||
|
|
@ -951,10 +940,15 @@ public:
|
|||
#endif
|
||||
|
||||
setOpaque (true);
|
||||
|
||||
wrapper.scaleManager.addListener (*this);
|
||||
wrapper.scaleManager.startObserving (*this);
|
||||
}
|
||||
|
||||
~EditorCompWrapper() override
|
||||
{
|
||||
wrapper.scaleManager.stopObserving (*this);
|
||||
wrapper.scaleManager.removeListener (*this);
|
||||
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.
|
||||
}
|
||||
|
|
@ -966,8 +960,8 @@ public:
|
|||
|
||||
void getEditorBounds (Vst2::ERect& bounds)
|
||||
{
|
||||
auto editorBounds = getSizeToContainChild();
|
||||
bounds = convertToHostBounds ({ 0, 0, (int16) editorBounds.getHeight(), (int16) editorBounds.getWidth() });
|
||||
auto editorBounds = getSizeToContainChild().toFloat().withZeroOrigin();
|
||||
bounds = createViewRect (wrapper.scaleManager.convertToHostBounds (editorBounds));
|
||||
}
|
||||
|
||||
void attachToHost (VstOpCodeArguments args)
|
||||
|
|
@ -989,9 +983,6 @@ public:
|
|||
// and we need to ensure that the X server knows that our window has been attached
|
||||
// before that happens.
|
||||
X11Symbols::getInstance()->xFlush (display);
|
||||
#elif JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
checkHostWindowScaleFactor (true);
|
||||
startTimer (500);
|
||||
#endif
|
||||
#elif JUCE_MAC
|
||||
hostWindow = detail::VSTWindowUtilities::attachComponentToWindowRefVST (this, desktopFlags, args.ptr);
|
||||
|
|
@ -1015,26 +1006,6 @@ public:
|
|||
return dynamic_cast<AudioProcessorEditor*> (getChildComponent (0));
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
if (auto* pluginEditor = getEditorComp())
|
||||
{
|
||||
if (! resizingParent)
|
||||
{
|
||||
auto newBounds = getLocalBounds();
|
||||
|
||||
{
|
||||
const ScopedValueSetter<bool> resizingChildSetter (resizingChild, true);
|
||||
pluginEditor->setBounds (pluginEditor->getLocalArea (this, newBounds).withPosition (0, 0));
|
||||
}
|
||||
|
||||
lastBounds = newBounds;
|
||||
}
|
||||
|
||||
updateWindowSize();
|
||||
}
|
||||
}
|
||||
|
||||
void parentSizeChanged() override
|
||||
{
|
||||
updateWindowSize();
|
||||
|
|
@ -1063,9 +1034,14 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
static Vst2::ERect createViewRect (juce::Rectangle<int> r)
|
||||
{
|
||||
return { (int16) r.getY(), (int16) r.getX(), (int16) r.getBottom(), (int16) r.getRight() };
|
||||
}
|
||||
|
||||
void resizeHostWindow (juce::Rectangle<int> bounds)
|
||||
{
|
||||
auto rect = convertToHostBounds ({ 0, 0, (int16) bounds.getHeight(), (int16) bounds.getWidth() });
|
||||
auto rect = createViewRect (wrapper.scaleManager.convertToHostBounds (bounds.toFloat()));
|
||||
const auto newWidth = rect.right - rect.left;
|
||||
const auto newHeight = rect.bottom - rect.top;
|
||||
|
||||
|
|
@ -1147,24 +1123,6 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
void setContentScaleFactor (float scale)
|
||||
{
|
||||
if (auto* pluginEditor = getEditorComp())
|
||||
{
|
||||
auto prevEditorBounds = pluginEditor->getLocalArea (this, lastBounds);
|
||||
|
||||
{
|
||||
const ScopedValueSetter<bool> resizingChildSetter (resizingChild, true);
|
||||
|
||||
pluginEditor->setScaleFactor (scale);
|
||||
pluginEditor->setBounds (prevEditorBounds.withPosition (0, 0));
|
||||
}
|
||||
|
||||
lastBounds = getSizeToContainChild();
|
||||
updateWindowSize();
|
||||
}
|
||||
}
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
void mouseDown (const MouseEvent&) override
|
||||
{
|
||||
|
|
@ -1179,24 +1137,14 @@ public:
|
|||
if (HWND parent = findMDIParentOf ((HWND) getWindowHandle()))
|
||||
SetWindowPos (parent, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
}
|
||||
|
||||
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
void checkHostWindowScaleFactor (bool force = false)
|
||||
{
|
||||
auto hostWindowScale = (float) getScaleFactorForWindow ((HostWindowType) hostWindow);
|
||||
|
||||
if (force || (hostWindowScale > 0.0f && ! approximatelyEqual (hostWindowScale, wrapper.editorScaleFactor)))
|
||||
wrapper.handleSetContentScaleFactor (hostWindowScale, force);
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
checkHostWindowScaleFactor();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
void peerBoundsDidUpdate() override
|
||||
{
|
||||
updateWindowSize();
|
||||
}
|
||||
|
||||
void updateWindowSize()
|
||||
{
|
||||
if (! resizingParent
|
||||
|
|
@ -1225,20 +1173,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static Vst2::ERect convertToHostBounds (const Vst2::ERect& rect)
|
||||
{
|
||||
auto desktopScale = Desktop::getInstance().getGlobalScaleFactor();
|
||||
|
||||
if (approximatelyEqual (desktopScale, 1.0f))
|
||||
return rect;
|
||||
|
||||
return { (int16) roundToInt (rect.top * desktopScale),
|
||||
(int16) roundToInt (rect.left * desktopScale),
|
||||
(int16) roundToInt (rect.bottom * desktopScale),
|
||||
(int16) roundToInt (rect.right * desktopScale) };
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_LINUX || JUCE_BSD
|
||||
SharedResourcePointer<detail::HostDrivenEventLoop> hostEventLoop;
|
||||
|
|
@ -1988,15 +1922,7 @@ private:
|
|||
const MessageManagerLock mmLock;
|
||||
#endif
|
||||
|
||||
#if ! JUCE_MAC
|
||||
if (force || ! approximatelyEqual (scale, editorScaleFactor))
|
||||
{
|
||||
editorScaleFactor = scale;
|
||||
|
||||
if (editorComp != nullptr)
|
||||
editorComp->setContentScaleFactor (editorScaleFactor);
|
||||
}
|
||||
#endif
|
||||
scaleManager.setHostScale (scale);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -2112,7 +2038,7 @@ private:
|
|||
CriticalSection stateInformationLock;
|
||||
juce::MemoryBlock chunkMemory;
|
||||
uint32 chunkMemoryTime = 0;
|
||||
float editorScaleFactor = 1.0f;
|
||||
detail::PluginScaleFactorManager scaleManager;
|
||||
std::unique_ptr<EditorCompWrapper> editorComp;
|
||||
Vst2::ERect editorRect;
|
||||
MidiBuffer midiEvents;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ JUCE_BEGIN_NO_SANITIZE ("vptr")
|
|||
#include <juce_audio_plugin_client/detail/juce_CheckSettingMacros.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_PluginUtilities.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_PluginScaleFactorUtilities.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_LinuxMessageThread.h>
|
||||
#include <juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h>
|
||||
#include <juce_gui_basics/native/juce_WindowsHooks_windows.h>
|
||||
|
|
@ -120,11 +121,6 @@ namespace juce
|
|||
|
||||
using namespace Steinberg;
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
double getScaleFactorForWindow (HWND);
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_LINUX || JUCE_BSD
|
||||
|
||||
|
|
@ -1672,9 +1668,7 @@ private:
|
|||
int lastLatencySamples = 0;
|
||||
bool blueCatPatchwork = isBlueCatHost (hostContext.get());
|
||||
|
||||
#if ! JUCE_MAC
|
||||
float lastScaleFactorReceived = 1.0f;
|
||||
#endif
|
||||
detail::PluginScaleFactorManager scaleManager;
|
||||
|
||||
InterfaceResultWithDeferredAddRef queryInterfaceInternal (const TUID targetIID)
|
||||
{
|
||||
|
|
@ -1995,27 +1989,9 @@ private:
|
|||
const auto desktopFlags = detail::PluginUtilities::getDesktopFlags (component->pluginEditor.get());
|
||||
|
||||
#if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
|
||||
// If the plugin was last opened at a particular scale, try to reapply that scale here.
|
||||
// Note that we do this during attach(), rather than in JuceVST3Editor(). During the
|
||||
// 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.
|
||||
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.
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
component->checkHostWindowScaleFactor();
|
||||
#endif
|
||||
|
||||
component->setOpaque (true);
|
||||
component->addToDesktop (desktopFlags, systemWindow);
|
||||
component->setVisible (true);
|
||||
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
component->startTimer (500);
|
||||
#endif
|
||||
|
||||
#else
|
||||
macHostWindow = detail::VSTWindowUtilities::attachComponentToWindowRefVST (component.get(), desktopFlags, parent);
|
||||
#endif
|
||||
|
|
@ -2062,12 +2038,12 @@ private:
|
|||
}
|
||||
|
||||
lastReportedSize.reset();
|
||||
rect = roundToViewRect (convertFromHostBounds (*newSize));
|
||||
|
||||
if (component == nullptr)
|
||||
return kResultTrue;
|
||||
|
||||
component->setSize (rect.getWidth(), rect.getHeight());
|
||||
const auto rounded = owner->scaleManager.convertFromHostBounds (createRectangle (*newSize)).toNearestIntEdges();
|
||||
component->onSize (rounded.getWidth(), rounded.getHeight());
|
||||
|
||||
#if JUCE_MAC
|
||||
if (cubase10Workaround != nullptr)
|
||||
|
|
@ -2078,7 +2054,11 @@ private:
|
|||
#endif
|
||||
{
|
||||
if (auto* peer = component->getPeer())
|
||||
peer->updateBounds();
|
||||
{
|
||||
peer->setBounds ((Rectangle { newSize->getWidth(), newSize->getHeight() }.toFloat()
|
||||
/ peer->getPlatformScaleFactor()).toNearestInt(),
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
return kResultTrue;
|
||||
|
|
@ -2091,15 +2071,12 @@ private:
|
|||
return kResultFalse;
|
||||
#endif
|
||||
|
||||
if (size == nullptr || component == nullptr)
|
||||
if (size == nullptr || component == nullptr || component->pluginEditor == nullptr)
|
||||
return kResultFalse;
|
||||
|
||||
const auto editorBounds = component->getSizeToContainChild();
|
||||
const auto sizeToReport = lastReportedSize.has_value()
|
||||
? *lastReportedSize
|
||||
: convertToHostBounds (editorBounds.withZeroOrigin().toFloat());
|
||||
|
||||
lastReportedSize = *size = sizeToReport;
|
||||
lastReportedSize = *size = lastReportedSize.value_or (createViewRect (owner->scaleManager.convertToHostBounds (editorBounds.withZeroOrigin().toFloat())));
|
||||
return kResultTrue;
|
||||
}
|
||||
|
||||
|
|
@ -2127,14 +2104,14 @@ private:
|
|||
auto constrainedRect = component->getLocalArea (editor, editor->getLocalBounds())
|
||||
.getSmallestIntegerContainer();
|
||||
|
||||
*rectToCheck = roundToViewRect (convertFromHostBounds (*rectToCheck));
|
||||
*rectToCheck = createViewRect (owner->scaleManager.convertFromHostBounds (createRectangle (*rectToCheck)).toNearestIntEdges());
|
||||
rectToCheck->right = rectToCheck->left + roundToInt (constrainedRect.getWidth());
|
||||
rectToCheck->bottom = rectToCheck->top + roundToInt (constrainedRect.getHeight());
|
||||
*rectToCheck = convertToHostBounds (createRectangle (*rectToCheck));
|
||||
*rectToCheck = createViewRect (owner->scaleManager.convertToHostBounds (createRectangle (*rectToCheck).toFloat()));
|
||||
}
|
||||
else if (auto* constrainer = editor->getConstrainer())
|
||||
{
|
||||
const auto clientBounds = convertFromHostBounds (*rectToCheck);
|
||||
const auto clientBounds = owner->scaleManager.convertFromHostBounds (createRectangle (*rectToCheck));
|
||||
const auto editorBounds = editor->getLocalArea (component.get(), clientBounds);
|
||||
|
||||
auto minW = (float) constrainer->getMinimumWidth();
|
||||
|
|
@ -2185,8 +2162,8 @@ private:
|
|||
|
||||
auto constrainedRect = component->getLocalArea (editor, Rectangle<float> (width, height));
|
||||
|
||||
*rectToCheck = convertToHostBounds (clientBounds.withWidth (constrainedRect.getWidth())
|
||||
.withHeight (constrainedRect.getHeight()));
|
||||
*rectToCheck = createViewRect (owner->scaleManager.convertToHostBounds (clientBounds.withWidth (constrainedRect.getWidth())
|
||||
.withHeight (constrainedRect.getHeight())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2200,14 +2177,14 @@ private:
|
|||
tresult PLUGIN_API setContentScaleFactor ([[maybe_unused]] const IPlugViewContentScaleSupport::ScaleFactor factor) override
|
||||
{
|
||||
#if ! JUCE_MAC
|
||||
const auto scaleToApply = [&]
|
||||
const auto scaleToApply = std::invoke ([&]
|
||||
{
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
// Cubase 10 only sends integer scale factors, so correct this for fractional scales
|
||||
if (detail::PluginUtilities::getHostType().type != PluginHostType::SteinbergCubase10)
|
||||
return factor;
|
||||
|
||||
const auto hostWindowScale = (IPlugViewContentScaleSupport::ScaleFactor) getScaleFactorForWindow (static_cast<HWND> (systemWindow));
|
||||
const auto hostWindowScale = (decltype (factor)) detail::PluginScaleFactorManager::getScaleFactorForWindow (static_cast<HWND> (systemWindow));
|
||||
|
||||
if (hostWindowScale <= 0.0 || approximatelyEqual (factor, hostWindowScale))
|
||||
return factor;
|
||||
|
|
@ -2216,9 +2193,9 @@ private:
|
|||
#else
|
||||
return factor;
|
||||
#endif
|
||||
}();
|
||||
});
|
||||
|
||||
applyScaleFactor (scaleFactor.withHost (scaleToApply));
|
||||
owner->scaleManager.setHostScale (scaleToApply);
|
||||
|
||||
return kResultTrue;
|
||||
#else
|
||||
|
|
@ -2277,53 +2254,36 @@ private:
|
|||
onSize (&viewRect);
|
||||
}
|
||||
|
||||
static ViewRect roundToViewRect (Rectangle<float> r)
|
||||
static ViewRect createViewRect (Rectangle<int> r)
|
||||
{
|
||||
const auto rounded = r.toNearestIntEdges();
|
||||
return { rounded.getX(),
|
||||
rounded.getY(),
|
||||
rounded.getRight(),
|
||||
rounded.getBottom() };
|
||||
return { r.getX(), r.getY(), r.getRight(), r.getBottom() };
|
||||
}
|
||||
|
||||
static Rectangle<float> createRectangle (ViewRect viewRect)
|
||||
static Rectangle<int> createRectangle (ViewRect viewRect)
|
||||
{
|
||||
return Rectangle<float>::leftTopRightBottom ((float) viewRect.left,
|
||||
(float) viewRect.top,
|
||||
(float) viewRect.right,
|
||||
(float) viewRect.bottom);
|
||||
}
|
||||
|
||||
static ViewRect convertToHostBounds (Rectangle<float> pluginRect)
|
||||
{
|
||||
const auto desktopScale = Desktop::getInstance().getGlobalScaleFactor();
|
||||
return roundToViewRect (approximatelyEqual (desktopScale, 1.0f) ? pluginRect
|
||||
: pluginRect * desktopScale);
|
||||
}
|
||||
|
||||
static Rectangle<float> convertFromHostBounds (ViewRect hostViewRect)
|
||||
{
|
||||
const auto desktopScale = Desktop::getInstance().getGlobalScaleFactor();
|
||||
const auto hostRect = createRectangle (hostViewRect);
|
||||
|
||||
return approximatelyEqual (desktopScale, 1.0f) ? hostRect
|
||||
: (hostRect / desktopScale);
|
||||
return Rectangle<int>::leftTopRightBottom ((int) viewRect.left,
|
||||
(int) viewRect.top,
|
||||
(int) viewRect.right,
|
||||
(int) viewRect.bottom);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct ContentWrapperComponent final : public Component
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
, public Timer
|
||||
#endif
|
||||
struct ContentWrapperComponent final : public Component,
|
||||
private detail::PluginScaleFactorManagerListener
|
||||
{
|
||||
ContentWrapperComponent (JuceVST3Editor& editor) : owner (editor)
|
||||
{
|
||||
setOpaque (true);
|
||||
setBroughtToFrontOnMouseClick (true);
|
||||
owner.owner->scaleManager.addListener (*this);
|
||||
owner.owner->scaleManager.startObserving (*this);
|
||||
}
|
||||
|
||||
~ContentWrapperComponent() override
|
||||
{
|
||||
owner.owner->scaleManager.stopObserving (*this);
|
||||
owner.owner->scaleManager.removeListener (*this);
|
||||
|
||||
if (pluginEditor != nullptr)
|
||||
{
|
||||
PopupMenu::dismissAllActiveMenus();
|
||||
|
|
@ -2349,19 +2309,11 @@ private:
|
|||
&owner);
|
||||
|
||||
pluginEditor->setHostContext (editorHostContext.get());
|
||||
#if ! JUCE_MAC
|
||||
pluginEditor->setScaleFactor (owner.scaleFactor.get());
|
||||
#endif
|
||||
|
||||
addAndMakeVisible (pluginEditor.get());
|
||||
pluginEditor->setTopLeftPosition (0, 0);
|
||||
|
||||
lastBounds = getSizeToContainChild();
|
||||
|
||||
{
|
||||
const ScopedValueSetter<bool> resizingParentSetter (resizingParent, true);
|
||||
setBounds (lastBounds);
|
||||
}
|
||||
setBounds (getSizeToContainChild());
|
||||
|
||||
resizeHostWindow();
|
||||
}
|
||||
|
|
@ -2377,7 +2329,7 @@ private:
|
|||
g.fillAll (Colours::black);
|
||||
}
|
||||
|
||||
juce::Rectangle<int> getSizeToContainChild()
|
||||
Rectangle<int> getSizeToContainChild()
|
||||
{
|
||||
if (pluginEditor != nullptr)
|
||||
return getLocalArea (pluginEditor.get(), pluginEditor->getLocalBounds());
|
||||
|
|
@ -2385,42 +2337,28 @@ private:
|
|||
return {};
|
||||
}
|
||||
|
||||
void onSize (int w, int h)
|
||||
{
|
||||
const ScopedValueSetter resizingChildSetter (resizingChild, true);
|
||||
|
||||
if (pluginEditor != nullptr)
|
||||
{
|
||||
const auto editorArea = pluginEditor->getLocalArea (this, Rectangle { w, h });
|
||||
pluginEditor->setBoundsConstrained (editorArea.withZeroOrigin());
|
||||
}
|
||||
}
|
||||
|
||||
void childBoundsChanged (Component*) override
|
||||
{
|
||||
if (resizingChild)
|
||||
return;
|
||||
|
||||
auto newBounds = getSizeToContainChild();
|
||||
resizeHostWindow();
|
||||
|
||||
if (newBounds != lastBounds)
|
||||
{
|
||||
resizeHostWindow();
|
||||
|
||||
#if JUCE_LINUX || JUCE_BSD
|
||||
if (detail::PluginUtilities::getHostType().isBitwigStudio())
|
||||
repaint();
|
||||
#endif
|
||||
|
||||
lastBounds = newBounds;
|
||||
}
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
if (pluginEditor != nullptr)
|
||||
{
|
||||
if (! resizingParent)
|
||||
{
|
||||
auto newBounds = getLocalBounds();
|
||||
|
||||
{
|
||||
const ScopedValueSetter<bool> resizingChildSetter (resizingChild, true);
|
||||
pluginEditor->setBounds (pluginEditor->getLocalArea (this, newBounds).withZeroOrigin());
|
||||
}
|
||||
|
||||
lastBounds = newBounds;
|
||||
}
|
||||
}
|
||||
#if JUCE_LINUX || JUCE_BSD
|
||||
if (detail::PluginUtilities::getHostType().isBitwigStudio())
|
||||
repaint();
|
||||
#endif
|
||||
}
|
||||
|
||||
void parentSizeChanged() override
|
||||
|
|
@ -2439,13 +2377,9 @@ private:
|
|||
if (owner.plugFrame != nullptr)
|
||||
{
|
||||
auto editorBounds = getSizeToContainChild();
|
||||
auto newSize = convertToHostBounds (editorBounds.withZeroOrigin().toFloat());
|
||||
|
||||
{
|
||||
const ScopedValueSetter<bool> resizingParentSetter (resizingParent, true);
|
||||
owner.plugFrame->resizeView (&owner, &newSize);
|
||||
}
|
||||
auto newSize = owner.createViewRect (owner.owner->scaleManager.convertToHostBounds (editorBounds.withZeroOrigin().toFloat()));
|
||||
|
||||
owner.plugFrame->resizeView (&owner, &newSize);
|
||||
auto host = detail::PluginUtilities::getHostType();
|
||||
|
||||
#if JUCE_MAC
|
||||
|
|
@ -2458,48 +2392,17 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void setEditorScaleFactor (float scale)
|
||||
{
|
||||
if (pluginEditor != nullptr)
|
||||
{
|
||||
auto prevEditorBounds = pluginEditor->getLocalArea (this, lastBounds);
|
||||
|
||||
{
|
||||
const ScopedValueSetter<bool> resizingChildSetter (resizingChild, true);
|
||||
|
||||
pluginEditor->setScaleFactor (scale);
|
||||
pluginEditor->setBounds (prevEditorBounds.withZeroOrigin());
|
||||
}
|
||||
|
||||
lastBounds = getSizeToContainChild();
|
||||
|
||||
resizeHostWindow();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
void checkHostWindowScaleFactor()
|
||||
{
|
||||
const auto estimatedScale = (float) getScaleFactorForWindow (static_cast<HWND> (owner.systemWindow));
|
||||
|
||||
if (estimatedScale > 0.0)
|
||||
owner.applyScaleFactor (owner.scaleFactor.withInternal (estimatedScale));
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
checkHostWindowScaleFactor();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<AudioProcessorEditor> pluginEditor;
|
||||
|
||||
private:
|
||||
void peerBoundsDidUpdate() override
|
||||
{
|
||||
resizeHostWindow();
|
||||
}
|
||||
|
||||
JuceVST3Editor& owner;
|
||||
std::unique_ptr<EditorHostContext> editorHostContext;
|
||||
Rectangle<int> lastBounds;
|
||||
bool resizingChild = false, resizingParent = false;
|
||||
bool resizingChild = false;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentWrapperComponent)
|
||||
};
|
||||
|
|
@ -2562,44 +2465,8 @@ private:
|
|||
};
|
||||
|
||||
std::unique_ptr<Cubase10WindowResizeWorkaround> cubase10Workaround;
|
||||
#else
|
||||
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<float> host;
|
||||
float internal = 1.0f;
|
||||
};
|
||||
|
||||
void applyScaleFactor (const StoredScaleFactor newFactor)
|
||||
{
|
||||
const auto previous = std::exchange (scaleFactor, newFactor).get();
|
||||
|
||||
if (approximatelyEqual (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
|
||||
detail::WindowsHooks hooks;
|
||||
#endif
|
||||
|
||||
#elif JUCE_WINDOWS
|
||||
detail::WindowsHooks hooks;
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue