1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +00:00

ComponentPeer: Add method for overriding native scale factor

This commit is contained in:
reuk 2025-09-18 16:21:03 +01:00
parent 6648e13fa6
commit b4c28db765
No known key found for this signature in database
3 changed files with 98 additions and 22 deletions

View file

@ -106,7 +106,7 @@ public:
updateScaleFactorFromNewBounds (bounds, false);
auto physicalBounds = parentWindow == 0 ? Desktop::getInstance().getDisplays().logicalToPhysical (bounds)
: bounds * currentScaleFactor;
: bounds * getPlatformScaleFactor();
WeakReference<Component> deletionChecker (&component);
@ -140,14 +140,14 @@ public:
{
auto physicalParentPosition = XWindowSystem::getInstance()->getPhysicalParentScreenPosition();
auto parentPosition = parentWindow == 0 ? Desktop::getInstance().getDisplays().physicalToLogical (physicalParentPosition)
: physicalParentPosition / currentScaleFactor;
: physicalParentPosition / getPlatformScaleFactor();
auto screenBounds = parentWindow == 0 ? bounds
: bounds.translated (parentPosition.x, parentPosition.y);
if (physical)
return parentWindow == 0 ? Desktop::getInstance().getDisplays().logicalToPhysical (screenBounds.getTopLeft())
: screenBounds.getTopLeft() * currentScaleFactor;
: screenBounds.getTopLeft() * getPlatformScaleFactor();
return screenBounds.getTopLeft();
}
@ -270,7 +270,7 @@ public:
if (trueIfInAChildWindow)
return true;
return XWindowSystem::getInstance()->contains (windowH, localPos * currentScaleFactor);
return XWindowSystem::getInstance()->contains (windowH, localPos * getPlatformScaleFactor());
}
void toFront (bool makeActive) override
@ -332,7 +332,24 @@ public:
double getPlatformScaleFactor() const noexcept override
{
return currentScaleFactor;
return scaleFactorOverride.value_or (currentScaleFactor);
}
void setCustomPlatformScaleFactor (std::optional<double> scaleIn) override
{
const auto prev = getPlatformScaleFactor();
scaleFactorOverride = scaleIn;
const auto next = getPlatformScaleFactor();
if (approximatelyEqual (prev, next))
return;
scaleFactorListeners.call ([&] (ScaleFactorListener& l) { l.nativeScaleFactorChanged (next); });
}
std::optional<double> getCustomPlatformScaleFactor() const override
{
return scaleFactorOverride;
}
void setAlpha (float) override {}
@ -386,7 +403,7 @@ public:
updateScaleFactorFromNewBounds (physicalBounds, true);
bounds = parentWindow == 0 ? Desktop::getInstance().getDisplays().physicalToLogical (physicalBounds)
: physicalBounds / currentScaleFactor;
: physicalBounds / getPlatformScaleFactor();
updateVBlankTimer();
}
@ -403,7 +420,7 @@ public:
windowBorder = [&]()
{
if (auto unscaledBorderSize = XWindowSystem::getInstance()->getBorderSize (windowH))
return OptionalBorderSize { (*unscaledBorderSize).multipliedBy (1.0 / currentScaleFactor) };
return OptionalBorderSize { (*unscaledBorderSize).multipliedBy (1.0 / getPlatformScaleFactor()) };
return OptionalBorderSize {};
}();
@ -460,7 +477,7 @@ private:
void repaint (Rectangle<int> area)
{
regionsNeedingRepaint.add (area * peer.currentScaleFactor);
regionsNeedingRepaint.add (area * peer.getPlatformScaleFactor());
}
void performAnyPendingRepaintsNow()
@ -511,7 +528,7 @@ private:
auto context = peer.getComponent().getLookAndFeel()
.createGraphicsContext (image, -totalArea.getPosition(), adjustedList);
context->addTransform (AffineTransform::scale ((float) peer.currentScaleFactor));
context->addTransform (AffineTransform::scale ((float) peer.getPlatformScaleFactor()));
peer.handlePaint (*context);
}
@ -607,6 +624,7 @@ private:
Rectangle<int> bounds;
ComponentPeer::OptionalBorderSize windowBorder;
bool fullScreen = false, isAlwaysOnTop = false;
std::optional<double> scaleFactorOverride;
double currentScaleFactor = 1.0;
Array<Component*> glRepaintListeners;
ScopedWindowAssociation association;

View file

@ -558,7 +558,8 @@ static Rectangle<ValueType> convertLogicalScreenRectangleToPhysical (Rectangle<V
return r;
}
static Point<int> convertPhysicalScreenPointToLogical (Point<int> p, HWND h) noexcept
template <typename ValueType>
static Point<ValueType> convertPhysicalScreenPointToLogical (Point<ValueType> p, HWND h) noexcept
{
if (isPerMonitorDPIAwareWindow (h))
return Desktop::getInstance().getDisplays().physicalToLogical (p, getCurrentDisplayFromScaleFactor (h));
@ -566,7 +567,8 @@ static Point<int> convertPhysicalScreenPointToLogical (Point<int> p, HWND h) noe
return p;
}
static Point<int> convertLogicalScreenPointToPhysical (Point<int> p, HWND h) noexcept
template <typename ValueType>
static Point<ValueType> convertLogicalScreenPointToPhysical (Point<ValueType> p, HWND h) noexcept
{
if (isPerMonitorDPIAwareWindow (h))
return Desktop::getInstance().getDisplays().logicalToPhysical (p, getCurrentDisplayFromScaleFactor (h));
@ -1471,8 +1473,19 @@ public:
return convertPhysicalScreenPointToLogical (getClientRectInScreen().getPosition(), hwnd);
}
Point<float> localToGlobal (Point<float> relativePosition) override { return relativePosition + getScreenPosition().toFloat(); }
Point<float> globalToLocal (Point<float> screenPosition) override { return screenPosition - getScreenPosition().toFloat(); }
Point<float> localToGlobal (Point<float> relativePosition) override
{
const auto localPhysical = relativePosition * getPlatformScaleFactor();
const auto physical = localPhysical + getClientRectInScreen().getPosition().toFloat();
return convertPhysicalScreenPointToLogical (physical, hwnd);
}
Point<float> globalToLocal (Point<float> screenPosition) override
{
const auto physical = convertLogicalScreenPointToPhysical (screenPosition, hwnd);
const auto localPhysical = physical - getClientRectInScreen().getPosition().toFloat();
return localPhysical / getPlatformScaleFactor();
}
using ComponentPeer::localToGlobal;
using ComponentPeer::globalToLocal;
@ -1578,12 +1591,13 @@ public:
bool contains (Point<int> localPos, bool trueIfInAChildWindow) const override
{
auto r = convertPhysicalScreenRectangleToLogical (D2DUtilities::toRectangle (getWindowScreenRect (hwnd)), hwnd);
const auto localPhysical = localPos.toFloat() / getPlatformScaleFactor();
auto r = D2DUtilities::toRectangle (getWindowScreenRect (hwnd)).toFloat();
if (! r.withZeroOrigin().contains (localPos))
if (! r.withZeroOrigin().contains (localPhysical))
return false;
const auto screenPos = convertLogicalScreenPointToPhysical (localPos + getScreenPosition(), hwnd);
const auto screenPos = (localPhysical + getClientRectInScreen().getPosition().toFloat()).roundToInt();
auto w = WindowFromPoint (D2DUtilities::toPOINT (screenPos));
return w == hwnd || (trueIfInAChildWindow && (IsChild (hwnd, w) != 0));
@ -1596,7 +1610,7 @@ public:
BorderSize<int> getFrameSize() const override
{
return findPhysicalBorderSize().value_or (BorderSize<int>{}).multipliedBy (1.0 / scaleFactor);
return findPhysicalBorderSize().value_or (BorderSize<int>{}).multipliedBy (1.0 / getPlatformScaleFactor());
}
bool setAlwaysOnTop (bool alwaysOnTop) override
@ -1993,7 +2007,7 @@ public:
return peer->doKeyUp (msg.wParam);
}
double getPlatformScaleFactor() const noexcept override
double getPlatformScaleFactorWithoutOverride() const noexcept
{
#if ! JUCE_WIN_PER_MONITOR_DPI_AWARE
return 1.0;
@ -2013,6 +2027,31 @@ public:
#endif
}
double getPlatformScaleFactor() const noexcept override
{
if (scaleFactorOverride.has_value())
return *scaleFactorOverride;
return getPlatformScaleFactorWithoutOverride();
}
void setCustomPlatformScaleFactor (std::optional<double> scaleIn) override
{
const auto prev = getPlatformScaleFactor();
scaleFactorOverride = scaleIn;
const auto next = getPlatformScaleFactor();
if (approximatelyEqual (prev, next))
return;
scaleFactorListeners.call ([&] (ScaleFactorListener& l) { l.nativeScaleFactorChanged (next); });
}
std::optional<double> getCustomPlatformScaleFactor() const override
{
return scaleFactorOverride;
}
static void getLastError()
{
TCHAR messageBuffer[256] = {};
@ -2065,7 +2104,6 @@ public:
}
bool hasTitleBar() const { return (styleFlags & windowHasTitleBar) != 0; }
double getScaleFactor() const { return scaleFactor; }
private:
HWND hwnd, parentToAddTo;
@ -2083,6 +2121,7 @@ private:
#endif
double scaleFactor = 1.0;
std::optional<double> scaleFactorOverride;
bool inDpiChange = 0, inHandlePositionChanged = 0;
HMONITOR currentMonitor = nullptr;
@ -4264,8 +4303,8 @@ private:
{
if (auto parentHwnd = GetParent (hwnd))
{
auto parentRect = convertPhysicalScreenRectangleToLogical (D2DUtilities::toRectangle (getWindowScreenRect (parentHwnd)), hwnd);
newBounds.translate (parentRect.getX(), parentRect.getY());
const auto parentRect = convertPhysicalScreenRectangleToLogical (D2DUtilities::toRectangle (getWindowScreenRect (parentHwnd)), hwnd);
newBounds += parentRect.getPosition();
}
}
@ -5787,7 +5826,7 @@ static const Displays::Display* getCurrentDisplayFromScaleFactor (HWND hwnd)
const auto scaleToLookFor = [&]
{
if (auto* peer = HWNDComponentPeer::getOwnerOfWindow (hwnd))
return peer->getPlatformScaleFactor();
return peer->getPlatformScaleFactorWithoutOverride();
return getScaleFactorForWindow (hwnd);
}();

View file

@ -544,6 +544,25 @@ public:
*/
virtual double getPlatformScaleFactor() const noexcept { return 1.0; }
/** On Windows and Linux, calling this with a non-null optional will override whatever scale
factor the platform has specified for this window. The new scale factor will persist even
in the case that the platform attempts to set a new scale! Pass a null optional to revert
back to the platform-provided scale.
This is intended for use by plugin wrappers, where hosts may attempt to set a scale factor
different from the platform scale. You should never need to call this directly.
*/
virtual void setCustomPlatformScaleFactor (std::optional<double>) {}
/** Returns the custom scale factor set using setCustomPlatformScaleFactor(), if any.
If a custom scale factor has been set, getPlatformScaleFactor() will always return that
value, effectively overriding any scale factor requested by the system.
Otherwise, if the custom platform scale factor is nullopt, then the system will update the
scale factor automatically.
*/
virtual std::optional<double> getCustomPlatformScaleFactor() const { return {}; }
/** On platforms that support it, this will update the window's titlebar in some
way to indicate that the window's document needs saving.
*/