From 27e75a70594aa99bc8cf80c99ab6dbd441bdc420 Mon Sep 17 00:00:00 2001 From: ed Date: Thu, 25 Nov 2021 15:49:39 +0000 Subject: [PATCH] DropShadower: Fix crash due to IsWindowOnCurrentVirtualDesktop() causing synchronous repaint messages during component destruction on Windows --- .../misc/juce_DropShadower.cpp | 20 ++++++++++++++----- .../juce_gui_basics/misc/juce_DropShadower.h | 3 ++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/modules/juce_gui_basics/misc/juce_DropShadower.cpp b/modules/juce_gui_basics/misc/juce_DropShadower.cpp index d8458df7cc..c98c4b7939 100644 --- a/modules/juce_gui_basics/misc/juce_DropShadower.cpp +++ b/modules/juce_gui_basics/misc/juce_DropShadower.cpp @@ -75,8 +75,8 @@ private: JUCE_DECLARE_NON_COPYABLE (ShadowWindow) }; -class ParentVisibilityChangedListener : public ComponentListener, - private Timer +class DropShadower::ParentVisibilityChangedListener : public ComponentListener, + private Timer { public: ParentVisibilityChangedListener (Component& r, ComponentListener& l) @@ -86,7 +86,10 @@ public: updateParentHierarchy (firstParent); if ((SystemStats::getOperatingSystemType() & SystemStats::Windows) != 0) - startTimerHz (20); + { + isOnVirtualDesktop = isWindowOnCurrentVirtualDesktop (root->getWindowHandle()); + startTimerHz (5); + } } ~ParentVisibilityChangedListener() override @@ -108,6 +111,8 @@ public: updateParentHierarchy (firstParent); } + bool isWindowOnVirtualDesktop() const noexcept { return isOnVirtualDesktop; } + private: class ComponentWithWeakReference { @@ -152,12 +157,17 @@ private: void timerCallback() override { - listener->componentVisibilityChanged (*root); + const auto wasOnVirtualDesktop = std::exchange (isOnVirtualDesktop, + isWindowOnCurrentVirtualDesktop (root->getWindowHandle())); + + if (isOnVirtualDesktop != wasOnVirtualDesktop) + listener->componentVisibilityChanged (*root); } Component* root = nullptr; ComponentListener* listener = nullptr; std::set observedComponents; + bool isOnVirtualDesktop = true; JUCE_DECLARE_NON_COPYABLE (ParentVisibilityChangedListener) JUCE_DECLARE_NON_MOVEABLE (ParentVisibilityChangedListener) @@ -259,7 +269,7 @@ void DropShadower::updateShadows() && owner->isShowing() && owner->getWidth() > 0 && owner->getHeight() > 0 && (Desktop::canUseSemiTransparentWindows() || owner->getParentComponent() != nullptr) - && isWindowOnCurrentVirtualDesktop (owner->getWindowHandle())) + && (visibilityChangedListener != nullptr && visibilityChangedListener->isWindowOnVirtualDesktop())) { while (shadowWindows.size() < 4) shadowWindows.add (new ShadowWindow (owner, shadow)); diff --git a/modules/juce_gui_basics/misc/juce_DropShadower.h b/modules/juce_gui_basics/misc/juce_DropShadower.h index b2927f7607..a142bd3bcd 100644 --- a/modules/juce_gui_basics/misc/juce_DropShadower.h +++ b/modules/juce_gui_basics/misc/juce_DropShadower.h @@ -75,7 +75,8 @@ private: void updateParent(); void updateShadows(); - std::unique_ptr visibilityChangedListener; + class ParentVisibilityChangedListener; + std::unique_ptr visibilityChangedListener; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower) };