From acddcd550d6dd88915c23a63f0b843bd820860d7 Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 14 Oct 2021 19:57:44 +0100 Subject: [PATCH] DropShadower: Detect when window is no longer being displayed on the current desktop and hide shadows --- modules/juce_gui_basics/juce_gui_basics.cpp | 53 ++++++++++++++++++- .../misc/juce_DropShadower.cpp | 25 +++++---- 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/modules/juce_gui_basics/juce_gui_basics.cpp b/modules/juce_gui_basics/juce_gui_basics.cpp index 521949f7bb..d150073588 100644 --- a/modules/juce_gui_basics/juce_gui_basics.cpp +++ b/modules/juce_gui_basics/juce_gui_basics.cpp @@ -122,6 +122,8 @@ namespace juce { return Process::isForegroundProcess() || isEmbeddedInForegroundProcess (viewComponent); } + + bool isWindowOnCurrentVirtualDesktop (void*); } #include "accessibility/juce_AccessibilityHandler.cpp" @@ -373,7 +375,56 @@ namespace juce } //============================================================================== -#if ! JUCE_WINDOWS +#if JUCE_WINDOWS +bool juce::isWindowOnCurrentVirtualDesktop (void* x) +{ + if (x == nullptr) + return false; + + static auto* desktopManager = [] + { + // IVirtualDesktopManager Copied from ShObjdl_core.h, because it may not be defined + MIDL_INTERFACE ("a5cd92ff-29be-454c-8d04-d82879fb3f1b") + juce_IVirtualDesktopManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsWindowOnCurrentVirtualDesktop( + __RPC__in HWND topLevelWindow, + __RPC__out BOOL * onCurrentDesktop) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetWindowDesktopId( + __RPC__in HWND topLevelWindow, + __RPC__out GUID * desktopId) = 0; + + virtual HRESULT STDMETHODCALLTYPE MoveWindowToDesktop( + __RPC__in HWND topLevelWindow, + __RPC__in REFGUID desktopId) = 0; + }; + + juce_IVirtualDesktopManager* result = nullptr; + + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token") + + class DECLSPEC_UUID("aa509086-5ca9-4c25-8f95-589d3c07b48a") juce_VirtualDesktopManager; + + if (SUCCEEDED (CoCreateInstance (__uuidof (juce_VirtualDesktopManager), nullptr, CLSCTX_ALL, IID_PPV_ARGS (&result)))) + return result; + + JUCE_END_IGNORE_WARNINGS_GCC_LIKE + + return static_cast (nullptr); + }(); + + BOOL current = false; + + if (auto* dm = desktopManager) + if (SUCCEEDED (dm->IsWindowOnCurrentVirtualDesktop (static_cast (x), ¤t))) + return current != false; + + return true; +} +#else + bool juce::isWindowOnCurrentVirtualDesktop (void*) { return true; } juce::ScopedDPIAwarenessDisabler::ScopedDPIAwarenessDisabler() { ignoreUnused (previousContext); } juce::ScopedDPIAwarenessDisabler::~ScopedDPIAwarenessDisabler() {} #endif diff --git a/modules/juce_gui_basics/misc/juce_DropShadower.cpp b/modules/juce_gui_basics/misc/juce_DropShadower.cpp index 6decf6d5f7..d8458df7cc 100644 --- a/modules/juce_gui_basics/misc/juce_DropShadower.cpp +++ b/modules/juce_gui_basics/misc/juce_DropShadower.cpp @@ -75,7 +75,8 @@ private: JUCE_DECLARE_NON_COPYABLE (ShadowWindow) }; -class ParentVisibilityChangedListener : public ComponentListener +class ParentVisibilityChangedListener : public ComponentListener, + private Timer { public: ParentVisibilityChangedListener (Component& r, ComponentListener& l) @@ -83,6 +84,9 @@ public: { if (auto* firstParent = root->getParentComponent()) updateParentHierarchy (firstParent); + + if ((SystemStats::getOperatingSystemType() & SystemStats::Windows) != 0) + startTimerHz (20); } ~ParentVisibilityChangedListener() override @@ -146,6 +150,11 @@ private: withDifference (observedComponents, lastSeenComponents, [this] (auto& comp) { comp.addComponentListener (this); }); } + void timerCallback() override + { + listener->componentVisibilityChanged (*root); + } + Component* root = nullptr; ComponentListener* listener = nullptr; std::set observedComponents; @@ -246,15 +255,11 @@ void DropShadower::updateShadows() const ScopedValueSetter setter (reentrant, true); - if (owner == nullptr) - { - shadowWindows.clear(); - return; - } - - if (owner->isShowing() - && owner->getWidth() > 0 && owner->getHeight() > 0 - && (Desktop::canUseSemiTransparentWindows() || owner->getParentComponent() != nullptr)) + if (owner != nullptr + && owner->isShowing() + && owner->getWidth() > 0 && owner->getHeight() > 0 + && (Desktop::canUseSemiTransparentWindows() || owner->getParentComponent() != nullptr) + && isWindowOnCurrentVirtualDesktop (owner->getWindowHandle())) { while (shadowWindows.size() < 4) shadowWindows.add (new ShadowWindow (owner, shadow));