mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-18 00:54:19 +00:00
OpenGL: Ensure that GL views display at the correct scale on macOS 12
Previously, we were using the window's top-left position to determine the scale to use for the OpenGLContext. However, on macOS the backingScaleFactor of the window is not strictly related to the top-left corner of the window, so the OpenGL view's scale could end up differing from the backing scale factor when slowly moving a window between displays with different backing scale factors. On macOS, we now use the backing scale factor of the window's screen (as maintained by AppKit), rather than trying to work out the correct display and scale ourselves.
This commit is contained in:
parent
72abf72c79
commit
ea8b0a2d32
1 changed files with 39 additions and 31 deletions
|
|
@ -161,13 +161,6 @@ public:
|
|||
|
||||
void resume()
|
||||
{
|
||||
#if JUCE_MAC
|
||||
initialDisplayTopLeft = Desktop::getInstance().getDisplays()
|
||||
.getDisplayForRect (component.getTopLevelComponent()->getScreenBounds())
|
||||
->totalArea
|
||||
.getTopLeft();
|
||||
#endif
|
||||
|
||||
if (renderThread != nullptr)
|
||||
renderThread->addJob (this, false);
|
||||
}
|
||||
|
|
@ -314,23 +307,26 @@ public:
|
|||
|
||||
if (auto* peer = component.getPeer())
|
||||
{
|
||||
auto localBounds = component.getLocalBounds();
|
||||
const auto currentDisplay = Desktop::getInstance().getDisplays().getDisplayForRect (component.getTopLevelComponent()->getScreenBounds());
|
||||
|
||||
if (currentDisplay != lastDisplay)
|
||||
#if JUCE_MAC
|
||||
const auto displayScale = [this]
|
||||
{
|
||||
#if JUCE_MAC
|
||||
if (cvDisplayLinkWrapper != nullptr)
|
||||
if (auto* wrapper = cvDisplayLinkWrapper.get())
|
||||
{
|
||||
cvDisplayLinkWrapper->updateActiveDisplay (currentDisplay->totalArea.getTopLeft());
|
||||
nativeContext->setNominalVideoRefreshPeriodS (cvDisplayLinkWrapper->getNominalVideoRefreshPeriodS());
|
||||
if (auto* screen = wrapper->updateAndReturnActiveDisplay())
|
||||
{
|
||||
nativeContext->setNominalVideoRefreshPeriodS (wrapper->getNominalVideoRefreshPeriodS());
|
||||
|
||||
return [screen backingScaleFactor];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
lastDisplay = currentDisplay;
|
||||
}
|
||||
|
||||
const auto displayScale = currentDisplay->scale;
|
||||
return scale;
|
||||
}();
|
||||
#else
|
||||
const auto displayScale = Desktop::getInstance().getDisplays().getDisplayForRect (component.getTopLevelComponent()->getScreenBounds())->scale;
|
||||
#endif
|
||||
|
||||
auto localBounds = component.getLocalBounds();
|
||||
auto newArea = peer->getComponent().getLocalArea (&component, localBounds).withZeroOrigin() * displayScale;
|
||||
|
||||
#if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE
|
||||
|
|
@ -590,7 +586,7 @@ public:
|
|||
|
||||
#if JUCE_MAC
|
||||
cvDisplayLinkWrapper = std::make_unique<CVDisplayLinkWrapper> (*this);
|
||||
cvDisplayLinkWrapper->updateActiveDisplay (initialDisplayTopLeft);
|
||||
cvDisplayLinkWrapper->updateAndReturnActiveDisplay();
|
||||
nativeContext->setNominalVideoRefreshPeriodS (cvDisplayLinkWrapper->getNominalVideoRefreshPeriodS());
|
||||
#endif
|
||||
|
||||
|
|
@ -709,13 +705,9 @@ public:
|
|||
OpenGLFrameBuffer cachedImageFrameBuffer;
|
||||
RectangleList<int> validArea;
|
||||
Rectangle<int> viewportArea, lastScreenBounds;
|
||||
const Displays::Display* lastDisplay = nullptr;
|
||||
double scale = 1.0;
|
||||
AffineTransform transform;
|
||||
GLuint vertexArrayObject = 0;
|
||||
#if JUCE_MAC
|
||||
Point<int> initialDisplayTopLeft;
|
||||
#endif
|
||||
|
||||
StringArray associatedObjectNames;
|
||||
ReferenceCountedArray<ReferenceCountedObject> associatedObjects;
|
||||
|
|
@ -752,15 +744,30 @@ public:
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void updateActiveDisplay (Point<int> topLeftOfDisplay)
|
||||
NSScreen* getCurrentScreen() const
|
||||
{
|
||||
CGDirectDisplayID displayID;
|
||||
uint32_t numDisplays = 0;
|
||||
constexpr uint32_t maxNumDisplays = 1;
|
||||
CGGetDisplaysWithPoint (convertToCGPoint (topLeftOfDisplay), maxNumDisplays, &displayID, &numDisplays);
|
||||
if (auto* peer = cachedImage.component.getPeer())
|
||||
if (auto* view = static_cast<NSView*> (peer->getNativeHandle()))
|
||||
if (auto* window = [view window])
|
||||
return [window screen];
|
||||
|
||||
if (numDisplays == 1)
|
||||
CVDisplayLinkSetCurrentCGDisplay (displayLink, displayID);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* If updated, returns the new screen, or nullptr otherwise. */
|
||||
NSScreen* updateAndReturnActiveDisplay()
|
||||
{
|
||||
auto* oldScreen = std::exchange (currentScreen, getCurrentScreen());
|
||||
|
||||
if (oldScreen == currentScreen)
|
||||
return nullptr;
|
||||
|
||||
for (NSScreen* screen in [NSScreen screens])
|
||||
if (screen == currentScreen)
|
||||
if (NSNumber* number = [[screen deviceDescription] objectForKey: @"NSScreenNumber"])
|
||||
CVDisplayLinkSetCurrentCGDisplay (displayLink, [number unsignedIntValue]);
|
||||
|
||||
return currentScreen;
|
||||
}
|
||||
|
||||
~CVDisplayLinkWrapper()
|
||||
|
|
@ -783,6 +790,7 @@ public:
|
|||
CachedImage& cachedImage;
|
||||
const bool continuousRepaint;
|
||||
CVDisplayLinkRef displayLink;
|
||||
NSScreen* currentScreen = nullptr;
|
||||
};
|
||||
|
||||
std::unique_ptr<CVDisplayLinkWrapper> cvDisplayLinkWrapper;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue