From c9daf4288d92218d9242f91aaf35ee3d5ca5b33a Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 21 Sep 2021 13:47:18 +0100 Subject: [PATCH] XWindowSystem: Only restack sibling windows Previously, BadMatch errors were seen when there were several modal windows, each with a native titlebar. Moving a window would attempt to restack the windows, which was not possible because the JUCE windows were not siblings. We actually need to restack the top level windows, i.e. the windows containing the server-side decorations. --- .../native/x11/juce_linux_XWindowSystem.cpp | 29 +++++++++++++++++-- .../native/x11/juce_linux_XWindowSystem.h | 2 ++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp index e595d9e527..4e38e7ed82 100644 --- a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp +++ b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp @@ -1920,10 +1920,13 @@ void XWindowSystem::toBehind (::Window windowH, ::Window otherWindow) const { jassert (windowH != 0 && otherWindow != 0); - Window newStack[] = { otherWindow, windowH }; + const auto topLevelA = findTopLevelWindowOf (windowH); + const auto topLevelB = findTopLevelWindowOf (otherWindow); + + Window newStack[] = { topLevelA, topLevelB }; XWindowSystemUtilities::ScopedXLock xLock; - X11Symbols::getInstance()->xRestackWindows (display, newStack, 2); + X11Symbols::getInstance()->xRestackWindows (display, newStack, numElementsInArray (newStack)); } bool XWindowSystem::isFocused (::Window windowH) const @@ -2653,6 +2656,28 @@ String XWindowSystem::getTextFromClipboard() const } //============================================================================== +::Window XWindowSystem::findTopLevelWindowOf (::Window w) const +{ + if (w == 0) + return 0; + + Window* windowList = nullptr; + uint32 windowListSize = 0; + Window parent, root; + + XWindowSystemUtilities::ScopedXLock xLock; + const auto result = X11Symbols::getInstance()->xQueryTree (display, w, &root, &parent, &windowList, &windowListSize); + const auto deleter = makeXFreePtr (windowList); + + if (result == 0) + return 0; + + if (parent == root) + return w; + + return findTopLevelWindowOf (parent); +} + bool XWindowSystem::isParentWindowOf (::Window windowH, ::Window possibleChild) const { if (windowH == 0 || possibleChild == 0) diff --git a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h index 947eff4661..eefb4b753b 100644 --- a/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h +++ b/modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h @@ -239,6 +239,8 @@ private: void dismissBlockingModals (LinuxComponentPeer*) const; void dismissBlockingModals (LinuxComponentPeer*, const XConfigureEvent&) const; + ::Window findTopLevelWindowOf (::Window) const; + static void windowMessageReceive (XEvent&); //==============================================================================