Setting a Linux Window Always on Top Without Re-creating the Peer


#1

Is there any way to set a Linux window to be alwaysOnTop without having to re-create the peer?
I’ve spent three days trying different ways to get plugin windows on Linux to behave correctly but they either disappear leaving a transparent, blocked, region on the screen, fall to the back when they should be always on top, open with a tiny size or the plugin UI fails to open and I’m left with just the window decorations. I can avoid one or the other of these problems but not all of then at once.

I have a feeling that if I can open the window as always on top, or at the very least set it without re-creating the peer, my resizing problems will go away. Is there any chance this can be implemented? Is this even possible on Linux?

bool setAlwaysOnTop (bool /* alwaysOnTop */) override
{
    return false;
}

#2

This should be feasible by setting the _NET_WM_STATE_ABOVE flag on the window (as suggested by https://stackoverflow.com/a/4347486).

Off hand I’m not sure how this translates into JUCE, so can’t help there…


#3

Hi @dave96,

In addition to my answer on this post:

the following diff should stop the peer from re-creating itself when you use setAlwaysOnTop. Can you confirm that this works for you? If yes, then I’ll push it to develop:

--- a/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp
+++ b/modules/juce_gui_basics/native/juce_linux_X11_Windowing.cpp
@@ -1818,9 +1818,18 @@ public:
		 return {};
	 }

-    bool setAlwaysOnTop (bool /* alwaysOnTop */) override
+    bool setAlwaysOnTop (bool alwaysOnTop) override
	 {
-        return false;
+        if (alwaysOnTop != isAlwaysOnTop)
+        {
+            numAlwaysOnTopPeers += (alwaysOnTop ? 1 : -1);
+            jassert (numAlwaysOnTopPeers >= 0);
+
+            ScopedXLock xlock (display);
+            setWindowType();
+        }
+
+        return true;
	 }

	 void toFront (bool makeActive) override

#4

Hmm, I don’t think this quite works (I think I tried something similar in the past).
It seems to bring the window to the front but not keep it always on top.

Does this work for you?
If you add the following lines to the bottom of the plugin host PluginWindow constructor:

SafePointer<PluginWindow> pw (this);
Timer::callAfterDelay (5000, [pw] () mutable { if (pw != nullptr) pw->setAlwaysOnTop (true); });

Then I open the host, open a plugin UI and click the graph panel to send the UI to the back. After 5 seconds the window jumps to the front but if I click on the graph window, it slips to the back again.


It looks like the the _NET_WM_STATE_ABOVE is a hint which the window manager can ignore? Perhaps this is what’s happening? Looking over Google it might be that the Urgency flag needs to be set instead? https://specifications.freedesktop.org/wm-spec/1.3/ar01s07.html#URGENCY