DropShadower impacting performance - recent JUCE change?

Probably not, IsWindowOnCurrentVirtualDesktop seems to be just slow. But I think I may have a different solution.
juce_ComponentPeer.h (25.1 KB)
juce_win32_Windowing.cpp (198.3 KB)
juce_DropShadower.h (2.8 KB)
juce_DropShadower.cpp (7.4 KB)

For the shadows, we need windows that don’t show on the taskbar, and also don’t show in all virtual desktops. App windows (WS_EX_APPWINDOW) always show on the taskbar, tool windows (WS_EX_TOOLWINDOW) show in all virtual desktops only if they are not owned. So we need tool windows owned by the shadower’s owner. addToDesktop takes a parent, not an owner: we have to bypass the setting of WS_CHILD, so I add a style flag to ComponentPeer, say

windowIsOwned = (1 << 12),

then in CreateWindow (juce_win32_windowing.cpp, line 2518)

else if (parentToAddTo != nullptr)
{
    if ((styleFlags & windowIsOwned) == 0)
        type |= WS_CHILD;
}

Now we can add the shadow windows with

addToDesktop (ComponentPeer::windowIgnoresMouseClicks
                | ComponentPeer::windowIsTemporary
                | ComponentPeer::windowIgnoresKeyPresses
             #if JUCE_WINDOWS
                | ComponentPeer::windowIsOwned,
              comp->getWindowHandle()
             #endif
             );

They won’t show on the taskbar, and also won’t show in all virtual desktops. I think this is an actual solution as opposed to a workaround: not only is IsWindowOnCurrentVirtualDesktop slow and invasive (it calls PeekMessage), we also got a delay before the shadows were shown or hidden.

A note about the “refactoring”. Having a separate class to handle parent visibility creates a back-and-forth link between two component listeners which is very simplified if it’s all done in the shadower. Given that observedComponents contains the whole hierarchy including the owner, there’s no need for lastParentComp, and updateParentHierarchy can handle all listener adds and removes. The behavior is equivalent except for componentChildrenChanged, where I say

if (owner != nullptr && owner->getParentComponent() == &c)
    updateShadows();

It seems to me that this handles z-order changes. As it was, it also reacted to changes inside the owner (between its children). I don’t see how these could affect the owner’s shadow. If they do, we can restore the previous behavior with

if (owner == &c || (owner != nullptr && owner->getParentComponent() == &c))
1 Like