diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp index c9c02f442a..60c121577d 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp @@ -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 (*this); - cvDisplayLinkWrapper->updateActiveDisplay (initialDisplayTopLeft); + cvDisplayLinkWrapper->updateAndReturnActiveDisplay(); nativeContext->setNominalVideoRefreshPeriodS (cvDisplayLinkWrapper->getNominalVideoRefreshPeriodS()); #endif @@ -709,13 +705,9 @@ public: OpenGLFrameBuffer cachedImageFrameBuffer; RectangleList validArea; Rectangle viewportArea, lastScreenBounds; - const Displays::Display* lastDisplay = nullptr; double scale = 1.0; AffineTransform transform; GLuint vertexArrayObject = 0; - #if JUCE_MAC - Point initialDisplayTopLeft; - #endif StringArray associatedObjectNames; ReferenceCountedArray associatedObjects; @@ -752,15 +744,30 @@ public: return 0.0; } - void updateActiveDisplay (Point 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 (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;