First off, I’m new to juce and very new to X11, so apologies in advance if my post doesn’t make sense
I’ve been trying to get a hosted plugin’s native editor window to stick on top of the host’s window (I named the function that should do this set_component_native_owning_window). I read that this can be accomplished with XSetTransientForHint, so I tried it, but the function fails every time, returning code 1. I tried using an error handler with XSetErrorHandler, but the handler callback never gets called, so I don’t know what exactly the error was
After that, I tried calling XStoreName with both windows, and it failed both times. So that leads me to believe that this is a general issue with X11 functions, not something specific to XSetTransientForHint
From there I did some poking around in juce’s files to see how it was calling X11 functions, and I discovered that juce doesn’t use the functions in Xlib.h directly. Instead it seems to load them dynamically as function pointers from libX11.so.6 in juce_XSymbols_linux.cpp and then call them like this: juce::X11Symbols::getInstance()->Xfunc().
At that point I started thinking that juce was just using a different version of X11 internally, and that these errors were the result of ABI incompatibilities, so I edited juce’s files to load XSetTransientForHint from the .so (they weren’t loaded by default), and edited my code to use juce::X11Symbols::getInstance() for all of my X11 calls
And the exact same error still occurred!
Honestly I’m at a loss. I must be doing something fundamentally wrong here. Can anyone that’s familiar with X11 help me out here?
My code:
#include "X11/Xlib.h"
int handler(Display * d, XErrorEvent * e) {
return 0; // the handler does nothing, I just set a breakpoint here to see if it gets called. It never does
}
void set_handler() { // I call this in my editor's constructor
XSetErrorHandler(handler);
}
void set_component_native_owning_window(juce::Component& to_be_owned, juce::Component& to_be_owner) {
auto display = XOpenDisplay(nullptr); // open the display referenced by the DISPLAY environment variable
if(display) {
auto to_be_owned_window = reinterpret_cast<Window>(to_be_owned.getWindowHandle()), // I inspected bit in gdb, and determined that the window handles have different values, so that isn't the issue
to_be_owner_window = reinterpret_cast<Window>(to_be_owner.getWindowHandle());
if(int ret = XSetTransientForHint(display, to_be_owner_window,
to_be_owned_window)) { // XSetTransientForHint failed. This happens every time
auto str = get_x_error(ret); // I inspect this variable from gdb
}
}
else { // XOpenDisplay failed. Doesn't happen in my testing
}
}
Miscellaneous information:
- distro is ubuntu
- DAW is reaper
- compiler is g++
- all function shown are called from the message thread
