mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-11 23:54:18 +00:00
DropShadower: Fix temporarily missing shadows, disable timer for non-desktop windows
This commit is contained in:
parent
3acc71f7df
commit
6c24b32bcd
2 changed files with 85 additions and 28 deletions
|
|
@ -86,20 +86,87 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE (ShadowWindow)
|
||||
};
|
||||
|
||||
class DropShadower::ParentVisibilityChangedListener : public ComponentListener,
|
||||
private Timer
|
||||
class DropShadower::VirtualDesktopWatcher final : public ComponentListener,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
VirtualDesktopWatcher (Component& c) : component (&c)
|
||||
{
|
||||
component->addComponentListener (this);
|
||||
update();
|
||||
}
|
||||
|
||||
~VirtualDesktopWatcher() override
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
if (auto* c = component.get())
|
||||
c->removeComponentListener (this);
|
||||
}
|
||||
|
||||
bool shouldHideDropShadow() const
|
||||
{
|
||||
return hasReasonToHide;
|
||||
}
|
||||
|
||||
void addListener (void* listener, std::function<void()> cb)
|
||||
{
|
||||
listeners[listener] = std::move (cb);
|
||||
}
|
||||
|
||||
void removeListener (void* listener)
|
||||
{
|
||||
listeners.erase (listener);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void componentParentHierarchyChanged (Component& c) override
|
||||
{
|
||||
if (component.get() == &c)
|
||||
update();
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
void update()
|
||||
{
|
||||
const auto newHasReasonToHide = [this]()
|
||||
{
|
||||
if (! component.wasObjectDeleted() && isWindows && component->isOnDesktop())
|
||||
{
|
||||
startTimerHz (5);
|
||||
return ! isWindowOnCurrentVirtualDesktop (component->getWindowHandle());
|
||||
}
|
||||
|
||||
stopTimer();
|
||||
return false;
|
||||
}();
|
||||
|
||||
if (std::exchange (hasReasonToHide, newHasReasonToHide) != newHasReasonToHide)
|
||||
for (auto& l : listeners)
|
||||
l.second();
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
WeakReference<Component> component;
|
||||
const bool isWindows = (SystemStats::getOperatingSystemType() & SystemStats::Windows) != 0;
|
||||
bool hasReasonToHide = false;
|
||||
std::map<void*, std::function<void()>> listeners;
|
||||
};
|
||||
|
||||
class DropShadower::ParentVisibilityChangedListener : public ComponentListener
|
||||
{
|
||||
public:
|
||||
ParentVisibilityChangedListener (Component& r, ComponentListener& l)
|
||||
: root (&r), listener (&l)
|
||||
{
|
||||
updateParentHierarchy();
|
||||
|
||||
if ((SystemStats::getOperatingSystemType() & SystemStats::Windows) != 0)
|
||||
{
|
||||
isOnVirtualDesktop = isWindowOnCurrentVirtualDesktop (root->getWindowHandle());
|
||||
startTimerHz (5);
|
||||
}
|
||||
}
|
||||
|
||||
~ParentVisibilityChangedListener() override
|
||||
|
|
@ -121,8 +188,6 @@ public:
|
|||
updateParentHierarchy();
|
||||
}
|
||||
|
||||
bool isWindowOnVirtualDesktop() const noexcept { return isOnVirtualDesktop; }
|
||||
|
||||
private:
|
||||
class ComponentWithWeakReference
|
||||
{
|
||||
|
|
@ -165,26 +230,9 @@ private:
|
|||
withDifference (observedComponents, lastSeenComponents, [this] (auto& comp) { comp.addComponentListener (this); });
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
WeakReference<DropShadower> deletionChecker { static_cast<DropShadower*> (listener) };
|
||||
|
||||
const auto wasOnVirtualDesktop = std::exchange (isOnVirtualDesktop,
|
||||
isWindowOnCurrentVirtualDesktop (root->getWindowHandle()));
|
||||
|
||||
// on Windows, isWindowOnCurrentVirtualDesktop() may cause synchronous messages to be dispatched
|
||||
// to the HWND so we need to check if the shadower is still valid after calling
|
||||
if (deletionChecker == nullptr)
|
||||
return;
|
||||
|
||||
if (isOnVirtualDesktop != wasOnVirtualDesktop)
|
||||
listener->componentVisibilityChanged (*root);
|
||||
}
|
||||
|
||||
Component* root = nullptr;
|
||||
ComponentListener* listener = nullptr;
|
||||
std::set<ComponentWithWeakReference> observedComponents;
|
||||
bool isOnVirtualDesktop = true;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (ParentVisibilityChangedListener)
|
||||
JUCE_DECLARE_NON_MOVEABLE (ParentVisibilityChangedListener)
|
||||
|
|
@ -195,6 +243,9 @@ DropShadower::DropShadower (const DropShadow& ds) : shadow (ds) {}
|
|||
|
||||
DropShadower::~DropShadower()
|
||||
{
|
||||
if (virtualDesktopWatcher != nullptr)
|
||||
virtualDesktopWatcher->removeListener (this);
|
||||
|
||||
if (owner != nullptr)
|
||||
{
|
||||
owner->removeComponentListener (this);
|
||||
|
|
@ -228,6 +279,9 @@ void DropShadower::setOwner (Component* componentToFollow)
|
|||
visibilityChangedListener = std::make_unique<ParentVisibilityChangedListener> (*owner,
|
||||
static_cast<ComponentListener&> (*this));
|
||||
|
||||
virtualDesktopWatcher = std::make_unique<VirtualDesktopWatcher> (*owner);
|
||||
virtualDesktopWatcher->addListener (this, [this]() { updateShadows(); });
|
||||
|
||||
updateShadows();
|
||||
}
|
||||
}
|
||||
|
|
@ -286,7 +340,7 @@ void DropShadower::updateShadows()
|
|||
&& owner->isShowing()
|
||||
&& owner->getWidth() > 0 && owner->getHeight() > 0
|
||||
&& (Desktop::canUseSemiTransparentWindows() || owner->getParentComponent() != nullptr)
|
||||
&& (visibilityChangedListener != nullptr && visibilityChangedListener->isWindowOnVirtualDesktop()))
|
||||
&& (virtualDesktopWatcher == nullptr || ! virtualDesktopWatcher->shouldHideDropShadow()))
|
||||
{
|
||||
while (shadowWindows.size() < 4)
|
||||
shadowWindows.add (new ShadowWindow (owner, shadow));
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ private:
|
|||
class ParentVisibilityChangedListener;
|
||||
std::unique_ptr<ParentVisibilityChangedListener> visibilityChangedListener;
|
||||
|
||||
class VirtualDesktopWatcher;
|
||||
std::unique_ptr<VirtualDesktopWatcher> virtualDesktopWatcher;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DropShadower)
|
||||
JUCE_DECLARE_WEAK_REFERENCEABLE (DropShadower)
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue