FR: Floating child windows

To quote another developer:

“This feature has been requested to death since 2006.”

I’m bringing it up again because this is still the number one feature I’d like to see in JUCE.

For desktop applications, the expected behaviour is that floating child windows stay on top of their parent window, while both the parent and child remain behind other applications. This is standard behaviour in many desktop apps and makes multi-window workflows much smoother. To get this basic behaviour, we are talking about relatively minor changes in the windowing code.

The community has already demonstrated workable solutions several times, including in the Floating child windows discussion. And my initial feature request in 2013.

I’d really appreciate seeing some attention given to refining JUCE’s windowing behaviour. It feels like a fundamental feature for standalone desktop applications and would significantly improve the overall user experience.

If sponsoring the development of a feature like this is an option, I’d be happy to hear more about how that works.

Hi, I’m the guy that wrote the floating child windows fork
Sorry for being an absentee maintainer… I pinky promise I’ll fix its issues and make it into a fully usable project so that (hopefully), these features can eventually end up in the official version of JUCE
I’ve been busy with my 9-5 lately, but I’m going to dedicate my weekends to this

Hi

Hi, that is great, and I’m grateful for your work. This is not a criticism of your fork, but more a request to merge this into the official Juce code. There is a limit to how many different juce versions for different fixes and tweaks I can manage to keep merging and resolving.

1 Like

I completely agree
I only created a fork as a temporary thing for demonstration purposes. It was always my intention to get this functionality into the official version of JUCE (assuming the maintainers accept my code, or at least like the end result enough to reimplement this feature themselves)
But thanks for your support!
I figure we’ll only get this feature into JUCE if we continue to make noise about it, so thanks for keeping this discussion alive

I’m new to the JUCE framework, but I have ran into the same problem as well.

It’s a very annoying problem when doing standalone application development, but the fix might be very easy to implement… at least on Windows.

The reason this is not working out of the box is that JUCE does not have the ability to set the owner of a window. If you use the addToDesktop function it forces the window style to a WS_CHILD. This makes the window to be only visible into his parent as you will now have a Parent → Child relation. This is good for a lot of stuff, but not if you want to have “floating” windows (known as tool/popup windows in Windows).

To force a Owner->Window relation you need to have the WS_POPUP style. JUCE will set this style but doensn’t allow to set the owner without it modifying this style flag. You can force this on Windows using this method:

ShellWindow::ShellWindow(const juce::String& title, int requiredButtons, juce::ComponentPeer *Owner)
: DocumentWindow(title, juce::LookAndFeel::getDefaultLookAndFeel().findColour(DefaultWindowBackgroundColorId), requiredButtons, true)
{
setUsingNativeTitleBar(false);
setResizable(true, false);

if (auto Peer = getPeer())
{
    auto Handle = (HWND) Peer->getNativeHandle();
    ::SetWindowLongPtr(Handle, GWLP_HWNDPARENT, (LONG_PTR)Owner->getNativeHandle());
}

}

(Sorry if there are obvious mistakes in the code, I’m just a hobby programmer)

This will set the owner of the newly created windows, effectively creating floating windows. Windows will take care of all the Z-ordering automatically.

It will also work with native titlebars, however Windows will only allow the close button (which makes sense).

In order NOT to have a taskbar icon/entry for this floating window, you can do this:

int ShellWindow::getDesktopWindowStyleFlags() const
{
    int styleFlags = DocumentWindow::getDesktopWindowStyleFlags();
    return styleFlags & ~juce::ComponentPeer::windowAppearsOnTaskbar;
}

You need to strip the windowsAppearsOnTaskbar flag, which gets automatically set by the TopLevelWindow class.

Now all of this has only be tested in my small scale app I’m developing, so there could be a lot of things that might go wrong in large scal apps.