Browse Source

Windows: Fixed a bug where bounds would be double scaled when using a non-default global scale factor

tags/2021-05-28
ed 6 years ago
parent
commit
81c0ec367e
3 changed files with 42 additions and 30 deletions
  1. +1
    -0
      modules/juce_gui_basics/desktop/juce_Desktop.h
  2. +18
    -9
      modules/juce_gui_basics/desktop/juce_Displays.cpp
  3. +23
    -21
      modules/juce_gui_basics/native/juce_win32_Windowing.cpp

+ 1
- 0
modules/juce_gui_basics/desktop/juce_Desktop.h View File

@@ -357,6 +357,7 @@ private:
friend class MouseInputSourceInternal;
friend class DeletedAtShutdown;
friend class TopLevelWindowManager;
friend class Displays;
std::unique_ptr<MouseInputSource::SourceList> mouseSources;


+ 18
- 9
modules/juce_gui_basics/desktop/juce_Displays.cpp View File

@@ -93,7 +93,9 @@ Rectangle<int> Displays::physicalToLogical (Rectangle<int> rect, const Display*
auto& display = useScaleFactorOfDisplay != nullptr ? *useScaleFactorOfDisplay
: findDisplayForRect (rect, true);
return ((rect.toFloat() - display.topLeftPhysical.toFloat()) / display.scale).toNearestInt() + display.totalArea.getTopLeft();
auto globalScale = Desktop::getInstance().getGlobalScaleFactor();
return ((rect.toFloat() - display.topLeftPhysical.toFloat()) / (display.scale / globalScale)).toNearestInt() + (display.totalArea.getTopLeft() * globalScale);
}
Rectangle<int> Displays::logicalToPhysical (Rectangle<int> rect, const Display* useScaleFactorOfDisplay) const noexcept
@@ -101,7 +103,9 @@ Rectangle<int> Displays::logicalToPhysical (Rectangle<int> rect, const Display*
auto& display = useScaleFactorOfDisplay != nullptr ? *useScaleFactorOfDisplay
: findDisplayForRect (rect, false);
return ((rect.toFloat() - display.totalArea.getTopLeft().toFloat()) * display.scale).toNearestInt() + display.topLeftPhysical;
auto globalScale = Desktop::getInstance().getGlobalScaleFactor();
return ((rect.toFloat() - (display.totalArea.getTopLeft().toFloat() * globalScale)) * (display.scale / globalScale)).toNearestInt() + display.topLeftPhysical;
}
template <typename ValueType>
@@ -110,10 +114,12 @@ Point<ValueType> Displays::physicalToLogical (Point<ValueType> point, const Disp
auto& display = useScaleFactorOfDisplay != nullptr ? *useScaleFactorOfDisplay
: findDisplayForPoint (point.roundToInt(), true);
auto globalScale = Desktop::getInstance().getGlobalScaleFactor();
Point<ValueType> logicalTopLeft (display.totalArea.getX(), display.totalArea.getY());
Point<ValueType> physicalTopLeft (display.topLeftPhysical.getX(), display.topLeftPhysical.getY());
return ((point - physicalTopLeft) / display.scale) + logicalTopLeft;
return ((point - physicalTopLeft) / (display.scale / globalScale)) + (logicalTopLeft * globalScale);
}
template <typename ValueType>
@@ -122,10 +128,12 @@ Point<ValueType> Displays::logicalToPhysical (Point<ValueType> point, const Disp
auto& display = useScaleFactorOfDisplay != nullptr ? *useScaleFactorOfDisplay
: findDisplayForPoint (point.roundToInt(), false);
auto globalScale = Desktop::getInstance().getGlobalScaleFactor();
Point<ValueType> logicalTopLeft (display.totalArea.getX(), display.totalArea.getY());
Point<ValueType> physicalTopLeft (display.topLeftPhysical.getX(), display.topLeftPhysical.getY());
return ((point - logicalTopLeft) * display.scale) + physicalTopLeft;
return ((point - (logicalTopLeft * globalScale)) * (display.scale / globalScale)) + physicalTopLeft;
}
const Displays::Display& Displays::getMainDisplay() const noexcept
@@ -252,8 +260,8 @@ static void processDisplay (DisplayNode* currentNode, const Array<DisplayNode>&
const auto logicalHeight = physicalArea.getHeight() / scale;
const auto physicalParentArea = currentNode->parent->display->totalArea.toDouble();
const auto logicalParentArea = currentNode->parent->logicalArea; // logical area of parent has already been calculated
const auto parentScale = currentNode->parent->display->scale;
const auto logicalParentArea = currentNode->parent->logicalArea; // logical area of parent has already been calculated
const auto parentScale = currentNode->parent->display->scale;
Rectangle<double> logicalArea (0.0, 0.0, logicalWidth, logicalHeight);
@@ -304,8 +312,9 @@ void Displays::updateToLogical()
if (displays.size() == 1)
{
auto& display = displays.getReference (0);
display.totalArea = (display.totalArea.toDouble() / display.scale).toNearestInt();
display.userArea = (display.userArea.toDouble() / display.scale).toNearestInt();
display.userArea = (display.userArea.toDouble() / display.scale).toNearestInt();
return;
}
@@ -346,8 +355,8 @@ void Displays::updateToLogical()
// Now set Display::totalArea and ::userArea using the logical area that we have calculated
node.display->topLeftPhysical = node.display->totalArea.getTopLeft();
node.display->totalArea = node.logicalArea.toNearestInt();
node.display->userArea = (relativeUserArea + node.logicalArea.getTopLeft()).toNearestInt();
node.display->totalArea = node.logicalArea.toNearestInt();
node.display->userArea = (relativeUserArea + node.logicalArea.getTopLeft()).toNearestInt();
}
}


+ 23
- 21
modules/juce_gui_basics/native/juce_win32_Windowing.cpp View File

@@ -531,7 +531,7 @@ static Point<int> convertLogicalScreenPointToPhysical (const Point<int>& p, HWND
static double getScaleFactorForWindow (HWND h)
{
if (isPerMonitorDPIAwareWindow (h) && getDPIForWindow != nullptr)
return ((double) getDPIForWindow (h) / USER_DEFAULT_SCREEN_DPI) * Desktop::getInstance().getGlobalScaleFactor();
return (double) getDPIForWindow (h) / USER_DEFAULT_SCREEN_DPI;
return 1.0;
}
@@ -1436,7 +1436,7 @@ public:
ShowWindow (hwnd, SW_SHOWNORMAL);
if (! boundsCopy.isEmpty())
setBounds (boundsCopy, false);
setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, boundsCopy), false);
}
else
{
@@ -2096,6 +2096,8 @@ private:
scaleFactor = Desktop::getInstance().getDisplays().getMainDisplay().scale;
else
scaleFactor = Desktop::getInstance().getDisplays().findDisplayForRect (bounds).scale;
scaleFactor /= Desktop::getInstance().getGlobalScaleFactor();
}
#endif
@@ -3117,14 +3119,14 @@ private:
Rectangle<int> getCurrentScaledBounds() const
{
return windowBorder.addedTo (ScalingHelpers::scaledScreenPosToUnscaled (component, component.getBounds()));
return ScalingHelpers::unscaledScreenPosToScaled (component, windowBorder.addedTo (ScalingHelpers::scaledScreenPosToUnscaled (component, component.getBounds())));
}
LRESULT handleSizeConstraining (RECT& r, const WPARAM wParam)
{
if (isConstrainedNativeWindow())
{
auto pos = convertPhysicalScreenRectangleToLogical (rectangleFromRECT (r), hwnd);
auto pos = ScalingHelpers::unscaledScreenPosToScaled (component, convertPhysicalScreenRectangleToLogical (rectangleFromRECT (r), hwnd));
auto current = getCurrentScaledBounds();
constrainer->checkBounds (pos, current,
@@ -3134,7 +3136,7 @@ private:
wParam == WMSZ_BOTTOM || wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_BOTTOMRIGHT,
wParam == WMSZ_RIGHT || wParam == WMSZ_TOPRIGHT || wParam == WMSZ_BOTTOMRIGHT);
r = RECTFromRectangle (convertLogicalScreenRectangleToPhysical (pos, hwnd));
r = RECTFromRectangle (convertLogicalScreenRectangleToPhysical (ScalingHelpers::scaledScreenPosToUnscaled (component, pos), hwnd));
}
return TRUE;
@@ -3148,7 +3150,7 @@ private:
&& (wp.x > -32000 && wp.y > -32000)
&& ! Component::isMouseButtonDownAnywhere())
{
auto pos = convertPhysicalScreenRectangleToLogical (rectangleFromRECT ({ wp.x, wp.y, wp.x + wp.cx, wp.y + wp.cy }), hwnd);
auto pos = ScalingHelpers::unscaledScreenPosToScaled (component, convertPhysicalScreenRectangleToLogical (rectangleFromRECT ({ wp.x, wp.y, wp.x + wp.cx, wp.y + wp.cy }), hwnd));
auto current = getCurrentScaledBounds();
constrainer->checkBounds (pos, current,
@@ -3158,7 +3160,7 @@ private:
pos.getY() == current.getY() && pos.getBottom() != current.getBottom(),
pos.getX() == current.getX() && pos.getRight() != current.getRight());
pos = convertLogicalScreenRectangleToPhysical (pos, hwnd);
pos = convertLogicalScreenRectangleToPhysical (ScalingHelpers::scaledScreenPosToUnscaled (component, pos), hwnd);
wp.x = pos.getX();
wp.y = pos.getY();
@@ -3195,7 +3197,7 @@ private:
LRESULT handleDPIChanging (int newDPI, RECT newRect)
{
auto newScale = ((double) newDPI / USER_DEFAULT_SCREEN_DPI) * Desktop::getInstance().getGlobalScaleFactor();
auto newScale = (double) newDPI / USER_DEFAULT_SCREEN_DPI;
if (! approximatelyEqual (scaleFactor, newScale))
{
@@ -4394,8 +4396,10 @@ static const Displays::Display* getCurrentDisplayFromScaleFactor (HWND hwnd)
else
scaleToLookFor = getScaleFactorForWindow (hwnd);
auto globalScale = Desktop::getInstance().getGlobalScaleFactor();
for (auto& d : Desktop::getInstance().getDisplays().displays)
if (approximatelyEqual (d.scale, scaleToLookFor))
if (approximatelyEqual (d.scale / globalScale, scaleToLookFor))
candidateDisplays.add (&d);
if (candidateDisplays.size() > 0)
@@ -4469,8 +4473,6 @@ void Displays::findDisplays (float masterScale)
setDPIAwareness();
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
auto isUsingPhysicalPixels = isPerMonitorDPIAwareProcess();
DPI_AWARENESS_CONTEXT prevContext = nullptr;
if (setThreadDPIAwarenessContext != nullptr && getAwarenessFromDPIAwarenessContext != nullptr && getThreadDPIAwarenessContext != nullptr
@@ -4507,16 +4509,11 @@ void Displays::findDisplays (float masterScale)
}
else
{
d.scale = d.dpi / USER_DEFAULT_SCREEN_DPI;
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
d.scale *= masterScale;
#endif
d.scale = (d.dpi / USER_DEFAULT_SCREEN_DPI) * (masterScale / Desktop::getDefaultMasterScale());
}
d.userArea = d.totalArea = Rectangle<int>::leftTopRightBottom (monitor.bounds.left, monitor.bounds.top,
monitor.bounds.right, monitor.bounds.bottom) / masterScale;
d.topLeftPhysical = d.totalArea.getPosition();
monitor.bounds.right, monitor.bounds.bottom);
if (d.isMain)
{
@@ -4524,19 +4521,24 @@ void Displays::findDisplays (float masterScale)
SystemParametersInfo (SPI_GETWORKAREA, 0, &workArea, 0);
d.userArea = d.userArea.getIntersection (Rectangle<int>::leftTopRightBottom (workArea.left, workArea.top,
workArea.right, workArea.bottom) / masterScale);
workArea.right, workArea.bottom));
}
displays.add (d);
}
#if JUCE_WIN_PER_MONITOR_DPI_AWARE
if (isUsingPhysicalPixels)
updateToLogical();
updateToLogical();
// Reset the DPI awareness context if it was overridden earlier
if (prevContext != nullptr)
setThreadDPIAwarenessContext (prevContext);
#else
for (auto& d : displays)
{
d.totalArea /= masterScale;
d.userArea /= masterScale;
}
#endif
}


Loading…
Cancel
Save