diff --git a/source/backend/plugin/CarlaPluginDSSI.cpp b/source/backend/plugin/CarlaPluginDSSI.cpp index 6159b8ddc..a7ffc52f3 100644 --- a/source/backend/plugin/CarlaPluginDSSI.cpp +++ b/source/backend/plugin/CarlaPluginDSSI.cpp @@ -148,19 +148,53 @@ public: #ifdef CARLA_OS_LINUX const ScopedEngineEnvironmentLocker _seel(kEngine); + // get current LD_PRELOAD, will restore it later const char* const oldPreload(std::getenv("LD_PRELOAD")); +# ifdef HAVE_X11 + // if the frontend uses winId parent, set LD_PRELOAD to auto-map the DSSI UI + const uintptr_t winId = kEngine->getOptions().frontendWinId; + + if (winId != 0) + { + char strBuf[STR_MAX+1]; + strBuf[STR_MAX] = '\0'; + std::snprintf(strBuf, STR_MAX, P_UINTPTR, kEngine->getOptions().frontendWinId); + ::setenv("CARLA_ENGINE_OPTION_FRONTEND_WIN_ID", strBuf, 1); + + CarlaString interposerPath(CarlaString(kEngine->getOptions().binaryDir) + + CARLA_OS_SEP_STR "libcarla_interposer-x11.so"); + ::setenv("LD_PRELOAD", interposerPath.buffer(), 1); + } + else +# else + // if no X11 or winId set, simply unset LD_PRELOAD + // (it might be set to libcarla_interposer-safe) if (oldPreload != nullptr) ::unsetenv("LD_PRELOAD"); -#endif +# endif +#endif // CARLA_OS_LINUX + // start the DSSI UI application carla_stdout("starting DSSI UI..."); started = fProcess->start(arguments); #ifdef CARLA_OS_LINUX + // restore initial state if (oldPreload != nullptr) + { ::setenv("LD_PRELOAD", oldPreload, 1); -#endif + } +# ifdef HAVE_X11 + if (winId != 0) + { + ::unsetenv("CARLA_ENGINE_OPTION_FRONTEND_WIN_ID"); + + if (oldPreload == nullptr) + ::unsetenv("LD_PRELOAD"); + } +# endif +#endif // CARLA_OS_LINUX } if (! started) diff --git a/source/interposer/Makefile b/source/interposer/Makefile index 1eaac6cad..85d436dba 100644 --- a/source/interposer/Makefile +++ b/source/interposer/Makefile @@ -22,6 +22,7 @@ endif # ---------------------------------------------------------------------------------------------------------------------------- BUILD_CXX_FLAGS += -I$(CWD)/includes -I$(CWD)/utils +LINK_FLAGS += -ldl # ---------------------------------------------------------------------------------------------------------------------------- diff --git a/source/interposer/interposer-x11.cpp b/source/interposer/interposer-x11.cpp index ad86a3e6b..fc69e12d0 100644 --- a/source/interposer/interposer-x11.cpp +++ b/source/interposer/interposer-x11.cpp @@ -17,11 +17,72 @@ #include "CarlaUtils.hpp" +#include #include +// ----------------------------------------------------------------------- +// Function typedefs + +typedef int (*XMapWindowFunc)(Display*, Window); +typedef int (*XUnmapWindowFunc)(Display*, Window); + +// ----------------------------------------------------------------------- +// Global counter so we only map the first (hopefully main) window + +static int sMapWindowCounter = 0; + +// ----------------------------------------------------------------------- +// Calling the real functions + +static int real_XMapWindow(Display* display, Window w) +{ + static XMapWindowFunc func = (XMapWindowFunc)::dlsym(RTLD_NEXT, "XMapWindow"); + CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); + + return func(display, w); +} + +static int real_XUnmapWindow(Display* display, Window w) +{ + static XUnmapWindowFunc func = (XUnmapWindowFunc)::dlsym(RTLD_NEXT, "XUnmapWindow"); + CARLA_SAFE_ASSERT_RETURN(func != nullptr, 0); + + return func(display, w); +} + +// ----------------------------------------------------------------------- +// Our custom functions + CARLA_EXPORT -int XMapWindow(Display* /*display*/, Window /*w*/) +int XMapWindow(Display* display, Window w) { carla_stdout("------------------------------- XMapWindow called"); - return 0; + + if (++sMapWindowCounter != 1) + return real_XMapWindow(display, w); + + if (const char* const winIdStr = std::getenv("CARLA_ENGINE_OPTION_FRONTEND_WIN_ID")) + { + CARLA_SAFE_ASSERT_RETURN(winIdStr[0] != '\0', real_XMapWindow(display, w)); + + const long long winId(std::strtoll(winIdStr, nullptr, 16)); + CARLA_SAFE_ASSERT_RETURN(winId >= 0, real_XMapWindow(display, w)); + + carla_stdout("Transient hint correctly applied before mapping window"); + XSetTransientForHint(display, w, static_cast(winId)); + } + + return real_XMapWindow(display, w); } + +CARLA_EXPORT +int XUnmapWindow(Display* display, Window w) +{ + carla_stdout("------------------------------- XUnmapWindow called"); + + --sMapWindowCounter; + + return real_XUnmapWindow(display, w); +} + +// ----------------------------------------------------------------------- diff --git a/source/utils/CarlaPluginUI.cpp b/source/utils/CarlaPluginUI.cpp index 66b99d3a4..6df306a7c 100644 --- a/source/utils/CarlaPluginUI.cpp +++ b/source/utils/CarlaPluginUI.cpp @@ -716,7 +716,7 @@ bool CarlaPluginUI::tryTransientWinIdMatch(const uintptr_t pid, const char* cons XSetTransientForHint(sd.display, lastGoodWindow, hostWinId); - if (centerUI) + if (centerUI && false /* moving the window after being shown isn't pretty... */) { int hostX, hostY, pluginX, pluginY; uint hostWidth, hostHeight, pluginWidth, pluginHeight, border, depth;