diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index 2716d8b707..fcfd9c3d73 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -83,9 +83,6 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4355) //============================================================================== namespace juce { -#if JUCE_WINDOWS - extern void setThreadDPIAwarenessForWindow (HWND); -#endif //============================================================================== namespace @@ -2865,7 +2862,7 @@ public: #if JUCE_WINDOWS if (pluginHWND != 0) { - setThreadDPIAwarenessForWindow (pluginHWND); + ScopedThreadDPIAwarenessSetter threadDpiAwarenessSetter { pluginHWND }; MoveWindow (pluginHWND, pos.getX(), pos.getY(), roundToInt (getWidth() * nativeScaleFactor), @@ -3128,7 +3125,7 @@ private: // very dodgy logic to decide which size is right. if (std::abs (rw - w) > 350 || std::abs (rh - h) > 350) { - setThreadDPIAwarenessForWindow (pluginHWND); + ScopedThreadDPIAwarenessSetter threadDpiAwarenessSetter { pluginHWND }; SetWindowPos (pluginHWND, 0, 0, 0, roundToInt (rw * nativeScaleFactor), roundToInt (rh * nativeScaleFactor), diff --git a/modules/juce_audio_processors/juce_audio_processors.cpp b/modules/juce_audio_processors/juce_audio_processors.cpp index 43ad88e1b4..36664e7cc5 100644 --- a/modules/juce_audio_processors/juce_audio_processors.cpp +++ b/modules/juce_audio_processors/juce_audio_processors.cpp @@ -35,6 +35,7 @@ #define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1 #define JUCE_CORE_INCLUDE_OBJC_HELPERS 1 #define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 +#define JUCE_GUI_BASICS_INCLUDE_SCOPED_THREAD_DPI_AWARENESS_SETTER 1 #include "juce_audio_processors.h" #include diff --git a/modules/juce_gui_basics/juce_gui_basics.cpp b/modules/juce_gui_basics/juce_gui_basics.cpp index c70541c991..12a815f6ba 100644 --- a/modules/juce_gui_basics/juce_gui_basics.cpp +++ b/modules/juce_gui_basics/juce_gui_basics.cpp @@ -41,6 +41,7 @@ #define JUCE_EVENTS_INCLUDE_WIN32_MESSAGE_WINDOW 1 #define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1 #define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 +#define JUCE_GUI_BASICS_INCLUDE_SCOPED_THREAD_DPI_AWARENESS_SETTER 1 #include "juce_gui_basics.h" diff --git a/modules/juce_gui_basics/juce_gui_basics.h b/modules/juce_gui_basics/juce_gui_basics.h index 615d8f630f..f323d6beba 100644 --- a/modules/juce_gui_basics/juce_gui_basics.h +++ b/modules/juce_gui_basics/juce_gui_basics.h @@ -342,6 +342,10 @@ namespace juce #endif #endif +#if JUCE_GUI_BASICS_INCLUDE_SCOPED_THREAD_DPI_AWARENESS_SETTER && JUCE_WINDOWS + #include "native/juce_win32_ScopedThreadDPIAwarenessSetter.h" +#endif + #include "layout/juce_FlexItem.h" #include "layout/juce_FlexBox.h" diff --git a/modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h b/modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h new file mode 100644 index 0000000000..c8990a7465 --- /dev/null +++ b/modules/juce_gui_basics/native/juce_win32_ScopedThreadDPIAwarenessSetter.h @@ -0,0 +1,43 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2020 - Raw Material Software Limited + + JUCE is an open source library subject to commercial or open-source + licensing. + + By using JUCE, you agree to the terms of both the JUCE 6 End-User License + Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). + + End User License Agreement: www.juce.com/juce-6-licence + Privacy Policy: www.juce.com/juce-privacy-policy + + Or: You may also use this code under the terms of the GPL v3 (see + www.gnu.org/licenses). + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +//============================================================================== +class ScopedThreadDPIAwarenessSetter +{ +public: + explicit ScopedThreadDPIAwarenessSetter (void* nativeWindow); + ~ScopedThreadDPIAwarenessSetter(); + +private: + class NativeImpl; + std::unique_ptr pimpl; + + JUCE_LEAK_DETECTOR (ScopedThreadDPIAwarenessSetter) +}; + +} // namespace juce diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp old mode 100755 new mode 100644 index 571ae637d7..7ac305c878 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -63,6 +63,12 @@ static bool shouldDeactivateTitleBar = true; void* getUser32Function (const char*); +#if JUCE_DEBUG + int numActiveScopedDpiAwarenessDisablers = 0; + bool isInScopedDPIAwarenessDisabler() { return numActiveScopedDpiAwarenessDisablers > 0; } + extern HWND juce_messageWindowHandle; +#endif + //============================================================================== #ifndef WM_TOUCH enum @@ -408,7 +414,10 @@ static void setDPIAwareness() static bool isPerMonitorDPIAwareProcess() { - #if JUCE_WIN_PER_MONITOR_DPI_AWARE + #if ! JUCE_WIN_PER_MONITOR_DPI_AWARE + return false; + #endif + static bool dpiAware = []() -> bool { setDPIAwareness(); @@ -423,40 +432,43 @@ static bool isPerMonitorDPIAwareProcess() }(); return dpiAware; - #else - return false; - #endif } -static bool isPerMonitorDPIAwareWindow (HWND h) +static bool isPerMonitorDPIAwareWindow (HWND nativeWindow) { - #if JUCE_WIN_PER_MONITOR_DPI_AWARE - jassert (h != nullptr); + #if ! JUCE_WIN_PER_MONITOR_DPI_AWARE + ignoreUnused (h); + return false; + #endif setDPIAwareness(); - if (getWindowDPIAwarenessContext != nullptr && getAwarenessFromDPIAwarenessContext != nullptr) - return getAwarenessFromDPIAwarenessContext (getWindowDPIAwarenessContext (h)) == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware; + if (getWindowDPIAwarenessContext != nullptr + && getAwarenessFromDPIAwarenessContext != nullptr) + { + return (getAwarenessFromDPIAwarenessContext (getWindowDPIAwarenessContext (nativeWindow)) + == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware); + } return isPerMonitorDPIAwareProcess(); - #else - ignoreUnused (h); - return false; - #endif } static bool isPerMonitorDPIAwareThread() { - #if JUCE_WIN_PER_MONITOR_DPI_AWARE + #if ! JUCE_WIN_PER_MONITOR_DPI_AWARE + return false; + #endif + setDPIAwareness(); - if (getThreadDPIAwarenessContext != nullptr && getAwarenessFromDPIAwarenessContext != nullptr) - return getAwarenessFromDPIAwarenessContext (getThreadDPIAwarenessContext()) == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware; + if (getThreadDPIAwarenessContext != nullptr + && getAwarenessFromDPIAwarenessContext != nullptr) + { + return (getAwarenessFromDPIAwarenessContext (getThreadDPIAwarenessContext()) + == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware); + } return isPerMonitorDPIAwareProcess(); - #else - return false; - #endif } static double getGlobalDPI() @@ -470,6 +482,83 @@ static double getGlobalDPI() } //============================================================================== +class ScopedThreadDPIAwarenessSetter::NativeImpl +{ +public: + explicit NativeImpl (HWND nativeWindow) + { + ignoreUnused (nativeWindow); + + #if JUCE_WIN_PER_MONITOR_DPI_AWARE + if (auto* functionSingleton = FunctionSingleton::getInstance()) + { + if (! functionSingleton->isLoaded()) + return; + + auto dpiAwareWindow = (functionSingleton->getAwarenessFromContext (functionSingleton->getWindowAwareness (nativeWindow)) + == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware); + + auto dpiAwareThread = (functionSingleton->getAwarenessFromContext (functionSingleton->getThreadAwareness()) + == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware); + + if (dpiAwareWindow && ! dpiAwareThread) + oldContext = functionSingleton->setThreadAwareness (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); + else if (! dpiAwareWindow && dpiAwareThread) + oldContext = functionSingleton->setThreadAwareness (DPI_AWARENESS_CONTEXT_UNAWARE); + } + #endif + } + + ~NativeImpl() + { + if (oldContext != nullptr) + if (auto* functionSingleton = FunctionSingleton::getInstance()) + functionSingleton->setThreadAwareness (oldContext); + } + +private: + struct FunctionSingleton : public DeletedAtShutdown + { + FunctionSingleton() = default; + ~FunctionSingleton() override { clearSingletonInstance(); } + + SetThreadDPIAwarenessContextFunc setThreadAwareness = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext"); + GetWindowDPIAwarenessContextFunc getWindowAwareness = (GetWindowDPIAwarenessContextFunc) getUser32Function ("GetWindowDpiAwarenessContext"); + GetThreadDPIAwarenessContextFunc getThreadAwareness = (GetThreadDPIAwarenessContextFunc) getUser32Function ("GetThreadDpiAwarenessContext"); + GetAwarenessFromDpiAwarenessContextFunc getAwarenessFromContext = (GetAwarenessFromDpiAwarenessContextFunc) getUser32Function ("GetAwarenessFromDpiAwarenessContext"); + + bool isLoaded() const noexcept + { + return setThreadAwareness != nullptr + && getWindowAwareness != nullptr + && getThreadAwareness != nullptr + && getAwarenessFromContext != nullptr; + } + + JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL (FunctionSingleton) + + JUCE_DECLARE_NON_COPYABLE (FunctionSingleton) + JUCE_DECLARE_NON_MOVEABLE (FunctionSingleton) + }; + + DPI_AWARENESS_CONTEXT oldContext = nullptr; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeImpl) + JUCE_DECLARE_NON_MOVEABLE (NativeImpl) +}; + + +JUCE_IMPLEMENT_SINGLETON (ScopedThreadDPIAwarenessSetter::NativeImpl::FunctionSingleton) + +ScopedThreadDPIAwarenessSetter::ScopedThreadDPIAwarenessSetter (void* nativeWindow) +{ + pimpl = std::make_unique ((HWND) nativeWindow); +} + +ScopedThreadDPIAwarenessSetter::~ScopedThreadDPIAwarenessSetter() +{ +} + #if JUCE_MODULE_AVAILABLE_juce_gui_extra ScopedDPIAwarenessDisabler::ScopedDPIAwarenessDisabler() { @@ -477,13 +566,25 @@ static double getGlobalDPI() return; if (setThreadDPIAwarenessContext != nullptr) + { previousContext = setThreadDPIAwarenessContext (DPI_AWARENESS_CONTEXT_UNAWARE); + + #if JUCE_DEBUG + ++numActiveScopedDpiAwarenessDisablers; + #endif + } } ScopedDPIAwarenessDisabler::~ScopedDPIAwarenessDisabler() { if (previousContext != nullptr) + { setThreadDPIAwarenessContext ((DPI_AWARENESS_CONTEXT) previousContext); + + #if JUCE_DEBUG + --numActiveScopedDpiAwarenessDisablers; + #endif + } } #endif @@ -527,6 +628,14 @@ static Point convertPhysicalScreenPointToLogical (Point p, HWND h) noe return p; } +static Point convertLogicalScreenPointToPhysical (Point p, HWND h) noexcept +{ + if (isPerMonitorDPIAwareWindow (h)) + return Desktop::getInstance().getDisplays().logicalToPhysical (p, getCurrentDisplayFromScaleFactor (h)); + + return p; +} + JUCE_API double getScaleFactorForWindow (HWND h) { // NB. Using a local function here because we need to call this method from the plug-in wrappers @@ -549,50 +658,11 @@ JUCE_API double getScaleFactorForWindow (HWND h) return 1.0; } -JUCE_API void setThreadDPIAwarenessForWindow (HWND nativeWindow) -{ - #if JUCE_WIN_PER_MONITOR_DPI_AWARE - // NB. Using local functions here because we need to call this method from the plug-in wrappers - // which don't load the DPI-awareness functions on startup - static SetThreadDPIAwarenessContextFunc localSetThreadDPIAwarenessContext = nullptr; - static GetWindowDPIAwarenessContextFunc localGetWindowDPIAwarenessContext = nullptr; - static GetThreadDPIAwarenessContextFunc localGetThreadDPIAwarenessContext = nullptr; - static GetAwarenessFromDpiAwarenessContextFunc localGetAwarenessFromDPIAwarenessContext = nullptr; - - static bool hasChecked = false; - static bool loadedOK = false; - - if (! hasChecked) - { - hasChecked = true; - - localSetThreadDPIAwarenessContext = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext"); - localGetWindowDPIAwarenessContext = (GetWindowDPIAwarenessContextFunc) getUser32Function ("GetWindowDpiAwarenessContext"); - localGetThreadDPIAwarenessContext = (GetThreadDPIAwarenessContextFunc) getUser32Function ("GetThreadDpiAwarenessContext"); - localGetAwarenessFromDPIAwarenessContext = (GetAwarenessFromDpiAwarenessContextFunc) getUser32Function ("GetAwarenessFromDpiAwarenessContext"); - - loadedOK = (localSetThreadDPIAwarenessContext != nullptr && localGetWindowDPIAwarenessContext != nullptr - && localGetThreadDPIAwarenessContext != nullptr && localGetAwarenessFromDPIAwarenessContext != nullptr); - } - - if (loadedOK) - { - auto dpiAwareWindow = localGetAwarenessFromDPIAwarenessContext (localGetWindowDPIAwarenessContext (nativeWindow)) == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware; - auto dpiAwareThread = localGetAwarenessFromDPIAwarenessContext (localGetThreadDPIAwarenessContext()) == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware; - - if (dpiAwareWindow && ! dpiAwareThread) - localSetThreadDPIAwarenessContext (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); - else if (! dpiAwareWindow && dpiAwareThread) - localSetThreadDPIAwarenessContext (DPI_AWARENESS_CONTEXT_UNAWARE); - } - #else - ignoreUnused (nativeWindow); - #endif -} - //============================================================================== static void setWindowPos (HWND hwnd, Rectangle bounds, UINT flags, bool adjustTopLeft = false) { + ScopedThreadDPIAwarenessSetter setter { hwnd }; + if (isPerMonitorDPIAwareWindow (hwnd)) { if (adjustTopLeft) @@ -607,9 +677,7 @@ static void setWindowPos (HWND hwnd, Rectangle bounds, UINT flags, bool adj static RECT getWindowScreenRect (HWND hwnd) { - #if JUCE_WIN_PER_MONITOR_DPI_AWARE - setThreadDPIAwarenessForWindow (hwnd); - #endif + ScopedThreadDPIAwarenessSetter setter { hwnd }; RECT rect; GetWindowRect (hwnd, &rect); @@ -621,7 +689,10 @@ static RECT getWindowClientRect (HWND hwnd) auto rect = getWindowScreenRect (hwnd); if (auto parentH = GetParent (hwnd)) + { + ScopedThreadDPIAwarenessSetter setter { hwnd }; MapWindowPoints (HWND_DESKTOP, parentH, (LPPOINT) &rect, 2); + } return rect; } @@ -634,14 +705,8 @@ static void setWindowZOrder (HWND hwnd, HWND insertAfter) //============================================================================== double Desktop::getDefaultMasterScale() { - if (! JUCEApplicationBase::isStandaloneApp() - #if JUCE_WIN_PER_MONITOR_DPI_AWARE - || isPerMonitorDPIAwareProcess() - #endif - ) - { + if (! JUCEApplicationBase::isStandaloneApp() || isPerMonitorDPIAwareProcess()) return 1.0; - } return getGlobalDPI() / USER_DEFAULT_SCREEN_DPI; } @@ -893,8 +958,8 @@ Image createSnapshotOfNativeWindow (void* nativeWindowHandle) auto hwnd = (HWND) nativeWindowHandle; auto r = convertPhysicalScreenRectangleToLogical (rectangleFromRECT (getWindowScreenRect (hwnd)), hwnd); - const int w = r.getWidth(); - const int h = r.getHeight(); + const auto w = r.getWidth(); + const auto h = r.getHeight(); auto nativeBitmap = new WindowsBitmapImage (Image::RGB, w, h, true); Image bitmap (nativeBitmap); @@ -1433,10 +1498,8 @@ public: auto localBounds = rectangleFromRECT (getWindowClientRect (hwnd)); - #if JUCE_WIN_PER_MONITOR_DPI_AWARE if (isPerMonitorDPIAwareWindow (hwnd)) return (localBounds.toDouble() / getPlatformScaleFactor()).toNearestInt(); - #endif return localBounds; }(); @@ -1554,16 +1617,10 @@ public: if (! r.withZeroOrigin().contains (localPos)) return false; - auto globalPos = localPos + getScreenPosition(); + auto w = WindowFromPoint (POINTFromPoint (convertLogicalScreenPointToPhysical (localPos + getScreenPosition(), + hwnd))); - #if JUCE_WIN_PER_MONITOR_DPI_AWARE - if (isPerMonitorDPIAwareThread() || isPerMonitorDPIAwareWindow (hwnd)) - globalPos = Desktop::getInstance().getDisplays().logicalToPhysical (globalPos); - #endif - - auto w = WindowFromPoint (POINTFromPoint (globalPos)); - - return w == hwnd || (trueIfInAChildWindow && (IsChild (hwnd, w) != 0)); + return w == hwnd || (trueIfInAChildWindow && (IsChild (hwnd, w) != 0)); } BorderSize getFrameSize() const override @@ -1663,18 +1720,7 @@ public: void repaint (const Rectangle& area) override { - auto scale = getPlatformScaleFactor(); - - #if JUCE_WIN_PER_MONITOR_DPI_AWARE - // if the calling thread is DPI-aware but we are invalidating a non-DPI aware window RECT, we actually have to - // divide the bounds by the scale factor as it will get multiplied for the virtualised paint callback... - if (isPerMonitorDPIAwareThread() && ! isPerMonitorDPIAwareWindow (hwnd)) - scale = 1.0 / Desktop::getInstance().getDisplays().getPrimaryDisplay()->scale; - #endif - - auto scaled = area.toDouble() * scale; - auto r = RECTFromRectangle (scaled.getSmallestIntegerContainer()); - + auto r = RECTFromRectangle ((area.toDouble() * getPlatformScaleFactor()).getSmallestIntegerContainer()); InvalidateRect (hwnd, &r, FALSE); } @@ -1795,19 +1841,8 @@ public: private: Point getMousePos (POINTL mousePos) const { - auto screenPos = pointFromPOINT ({ mousePos.x, mousePos.y }).toFloat(); - - #if JUCE_WIN_PER_MONITOR_DPI_AWARE - auto h = (HWND) peer.getNativeHandle(); - - if (isPerMonitorDPIAwareWindow (h)) - screenPos = convertPhysicalScreenPointToLogical (screenPos.roundToInt(), h).toFloat(); - #else - if (JUCEApplication::isStandaloneApp()) - screenPos /= static_cast (getGlobalDPI() / USER_DEFAULT_SCREEN_DPI); - #endif - - return peer.getComponent().getLocalPoint (nullptr, screenPos); + return peer.getComponent().getLocalPoint (nullptr, convertPhysicalScreenPointToLogical (pointFromPOINT ({ mousePos.x, mousePos.y }), + (HWND) peer.getNativeHandle()).toFloat()); } struct DroppedData @@ -1902,7 +1937,10 @@ public: double getPlatformScaleFactor() const noexcept override { - #if JUCE_WIN_PER_MONITOR_DPI_AWARE + #if ! JUCE_WIN_PER_MONITOR_DPI_AWARE + return 1.0; + #endif + if (! isPerMonitorDPIAwareWindow (hwnd)) return 1.0; @@ -1916,9 +1954,6 @@ public: } return scaleFactor; - #else - return 1.0; - #endif } private: @@ -2153,6 +2188,14 @@ private: L"", type, 0, 0, 0, 0, parentToAddTo, nullptr, (HINSTANCE) Process::getCurrentModuleInstanceHandle(), nullptr); + #if JUCE_DEBUG + // The DPI-awareness context of this window and JUCE's hidden message window are different. + // You normally want these to match otherwise timer events and async messages will happen + // in a different context to normal HWND messages which can cause issues with UI scaling. + jassert (isPerMonitorDPIAwareWindow (hwnd) == isPerMonitorDPIAwareWindow (juce_messageWindowHandle) + || isInScopedDPIAwarenessDisabler()); + #endif + if (hwnd != nullptr) { SetWindowLongPtr (hwnd, 0, 0); @@ -2179,19 +2222,8 @@ private: setDPIAwareness(); - #if JUCE_WIN_PER_MONITOR_DPI_AWARE if (isPerMonitorDPIAwareThread()) - { - auto bounds = component.getBounds(); - - if (bounds.isEmpty()) - scaleFactor = Desktop::getInstance().getDisplays().getPrimaryDisplay()->scale; - else - scaleFactor = Desktop::getInstance().getDisplays().getDisplayForRect (bounds)->scale; - - scaleFactor /= Desktop::getInstance().getGlobalScaleFactor(); - } - #endif + scaleFactor = getScaleFactorForWindow (hwnd); setMessageFilter(); updateBorderSize(); @@ -3508,20 +3540,18 @@ private: Point getPointFromLocalLParam (LPARAM lParam) noexcept { - #if JUCE_WIN_PER_MONITOR_DPI_AWARE + auto p = pointFromPOINT (getPOINTFromLParam (lParam)); + if (isPerMonitorDPIAwareWindow (hwnd)) { // LPARAM is relative to this window's top-left but may be on a different monitor so we need to calculate the // physical screen position and then convert this to local logical coordinates - auto localPos = getPOINTFromLParam (lParam); auto r = getWindowScreenRect (hwnd); - - return globalToLocal (Desktop::getInstance().getDisplays().physicalToLogical (pointFromPOINT ({ r.left + localPos.x + roundToInt (windowBorder.getLeft() * scaleFactor), - r.top + localPos.y + roundToInt (windowBorder.getTop() * scaleFactor) })).toFloat()); + return globalToLocal (Desktop::getInstance().getDisplays().physicalToLogical (pointFromPOINT ({ r.left + p.x + roundToInt (windowBorder.getLeft() * scaleFactor), + r.top + p.y + roundToInt (windowBorder.getTop() * scaleFactor) })).toFloat()); } - #endif - return { static_cast (GET_X_LPARAM (lParam)), static_cast (GET_Y_LPARAM (lParam)) }; + return p.toFloat(); } Point getCurrentMousePos() noexcept @@ -4431,10 +4461,8 @@ Point MouseInputSource::getCurrentRawMousePosition() auto p = pointFromPOINT (mousePos); - #if JUCE_WIN_PER_MONITOR_DPI_AWARE if (isPerMonitorDPIAwareThread()) p = Desktop::getInstance().getDisplays().physicalToLogical (p); - #endif return p.toFloat(); } diff --git a/modules/juce_gui_extra/embedding/juce_ScopedDPIAwarenessDisabler.h b/modules/juce_gui_extra/embedding/juce_ScopedDPIAwarenessDisabler.h old mode 100644 new mode 100755 diff --git a/modules/juce_gui_extra/juce_gui_extra.cpp b/modules/juce_gui_extra/juce_gui_extra.cpp old mode 100644 new mode 100755 index 9e813c0e7a..5dc0f13a2e --- a/modules/juce_gui_extra/juce_gui_extra.cpp +++ b/modules/juce_gui_extra/juce_gui_extra.cpp @@ -39,6 +39,7 @@ #define JUCE_EVENTS_INCLUDE_WIN32_MESSAGE_WINDOW 1 #define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1 #define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 +#define JUCE_GUI_BASICS_INCLUDE_SCOPED_THREAD_DPI_AWARENESS_SETTER 1 #ifndef JUCE_PUSH_NOTIFICATIONS #define JUCE_PUSH_NOTIFICATIONS 0 diff --git a/modules/juce_gui_extra/native/juce_win32_HWNDComponent.cpp b/modules/juce_gui_extra/native/juce_win32_HWNDComponent.cpp index 905e137840..7ab2dd5613 100644 --- a/modules/juce_gui_extra/native/juce_win32_HWNDComponent.cpp +++ b/modules/juce_gui_extra/native/juce_win32_HWNDComponent.cpp @@ -26,8 +26,6 @@ namespace juce { -void setThreadDPIAwarenessForWindow (HWND); - class HWNDComponent::Pimpl : public ComponentMovementWatcher { public: @@ -52,13 +50,13 @@ public: { auto area = (peer->getAreaCoveredBy (owner).toFloat() * peer->getPlatformScaleFactor()).getSmallestIntegerContainer(); - setThreadDPIAwarenessForWindow (hwnd); - UINT flagsToSend = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER; if (! wasMoved) flagsToSend |= SWP_NOMOVE; if (! wasResized) flagsToSend |= SWP_NOSIZE; + ScopedThreadDPIAwarenessSetter threadDpiAwarenessSetter { hwnd }; + SetWindowPos (hwnd, nullptr, area.getX(), area.getY(), area.getWidth(), area.getHeight(), flagsToSend); } } @@ -101,7 +99,7 @@ public: { if (auto* peer = owner.getPeer()) { - setThreadDPIAwarenessForWindow (hwnd); + ScopedThreadDPIAwarenessSetter threadDpiAwarenessSetter { hwnd }; RECT r; GetWindowRect (hwnd, &r); diff --git a/modules/juce_opengl/juce_opengl.cpp b/modules/juce_opengl/juce_opengl.cpp index 76754ae0f5..b6b4e6daeb 100644 --- a/modules/juce_opengl/juce_opengl.cpp +++ b/modules/juce_opengl/juce_opengl.cpp @@ -37,6 +37,7 @@ #define JUCE_CORE_INCLUDE_NATIVE_HEADERS 1 #define JUCE_GRAPHICS_INCLUDE_COREGRAPHICS_HELPERS 1 #define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1 +#define JUCE_GUI_BASICS_INCLUDE_SCOPED_THREAD_DPI_AWARENESS_SETTER 1 #include "juce_opengl.h" diff --git a/modules/juce_opengl/native/juce_OpenGL_win32.h b/modules/juce_opengl/native/juce_OpenGL_win32.h index 6106fce546..d8c892ce82 100644 --- a/modules/juce_opengl/native/juce_OpenGL_win32.h +++ b/modules/juce_opengl/native/juce_OpenGL_win32.h @@ -28,10 +28,6 @@ namespace juce extern ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component&, void* parent); -#if JUCE_WIN_PER_MONITOR_DPI_AWARE - extern void setThreadDPIAwarenessForWindow (HWND); -#endif - //============================================================================== class OpenGLContext::NativeContext #if JUCE_WIN_PER_MONITOR_DPI_AWARE @@ -97,15 +93,17 @@ public: bool initialiseOnRenderThread (OpenGLContext& c) { - #if JUCE_WIN_PER_MONITOR_DPI_AWARE - setThreadDPIAwarenessForWindow ((HWND) nativeWindow->getNativeHandle()); - #endif - + threadAwarenessSetter = std::make_unique (nativeWindow->getNativeHandle()); context = &c; return true; } - void shutdownOnRenderThread() { deactivateCurrentContext(); context = nullptr; } + void shutdownOnRenderThread() + { + deactivateCurrentContext(); + context = nullptr; + threadAwarenessSetter = nullptr; + } static void deactivateCurrentContext() { wglMakeCurrent (nullptr, nullptr); } bool makeActive() const noexcept { return isActive() || wglMakeCurrent (dc, renderContext) != FALSE; } @@ -170,6 +168,7 @@ private: std::unique_ptr dummyComponent; std::unique_ptr nativeWindow; + std::unique_ptr threadAwarenessSetter; HGLRC renderContext; HDC dc; OpenGLContext* context = {}; @@ -219,7 +218,13 @@ private: void createNativeWindow (Component& component) { auto* topComp = component.getTopLevelComponent(); - nativeWindow.reset (createNonRepaintingEmbeddedWindowsPeer (*dummyComponent, topComp->getWindowHandle())); + + { + auto* parentHWND = topComp->getWindowHandle(); + + ScopedThreadDPIAwarenessSetter setter { parentHWND }; + nativeWindow.reset (createNonRepaintingEmbeddedWindowsPeer (*dummyComponent, parentHWND)); + } if (auto* peer = topComp->getPeer()) {