From a788a3babcd2076c0652ec6bb35c5016b0c99ce8 Mon Sep 17 00:00:00 2001 From: Filippo Luca Ferretti <102977828+flferretti@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:45:41 +0100 Subject: [PATCH] Enable runtime window system selection on Linux in `iDynTree::Visualizer` (#1223) Co-authored-by: Silvio Traversaro <silvio@traversaro.it> --- src/visualization/CMakeLists.txt | 19 ++++++++++++++++++ src/visualization/src/Visualizer.cpp | 29 +++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/visualization/CMakeLists.txt b/src/visualization/CMakeLists.txt index 7907eb7c71..ed2e6ed184 100644 --- a/src/visualization/CMakeLists.txt +++ b/src/visualization/CMakeLists.txt @@ -97,6 +97,25 @@ if(IDYNTREE_USES_IRRLICHT) find_library(IOKIT_LIBRARY IOKit) target_link_libraries(${libraryname} LINK_PRIVATE ${CARBON_LIBRARY} ${COCOA_LIBRARY} ${IOKIT_LIBRARY}) endif () + + # On Linux, in some system for some reason creating a windows with X does not work, but creating it with Wayland + # yes. For this reason, we expose an option to permit to try to create a glfw window via wayland. This is an + # option and is not enabled by default as the glfw version shipped via apt with Ubuntu version before 24.10, so + # we expose this as an option and we enable it by default only if we are configuring inside a conda environment + # Once we drop support for apt dependencies on Ubuntu 24.04, we will be able to remove this code and always + # try wayland first + if(NOT WIN32 AND NOT APPLE) + if(DEFINED ENV{CONDA_PREFIX}) + set(IDYNTREE_GLFW_TRY_WAYLAND_FIRST_DEFAULT_VALUE ON) + else() + set(IDYNTREE_GLFW_TRY_WAYLAND_FIRST_DEFAULT_VALUE OFF) + endif() + option(IDYNTREE_GLFW_TRY_WAYLAND_FIRST "If enabled, when creating a window iDynTree will try first to use wayland and only on failure X11" ${IDYNTREE_GLFW_TRY_WAYLAND_FIRST_DEFAULT_VALUE}) + mark_as_advanced(IDYNTREE_GLFW_TRY_WAYLAND_FIRST) + if(IDYNTREE_GLFW_TRY_WAYLAND_FIRST) + add_definitions(-DIDYNTREE_GLFW_TRY_WAYLAND_FIRST) + endif() + endif() endif() if(IDYNTREE_USES_MESHCATCPP) diff --git a/src/visualization/src/Visualizer.cpp b/src/visualization/src/Visualizer.cpp index d76f7311f0..302ff639f9 100644 --- a/src/visualization/src/Visualizer.cpp +++ b/src/visualization/src/Visualizer.cpp @@ -26,6 +26,9 @@ #define GLFW_EXPOSE_NATIVE_NSGL #elif defined(__linux__) #define GLFW_EXPOSE_NATIVE_X11 + #if defined(IDYNTREE_GLFW_TRY_WAYLAND_FIRST) + #define GLFW_EXPOSE_NATIVE_WAYLAND + #endif #define GLFW_EXPOSE_NATIVE_GLX #endif @@ -162,7 +165,7 @@ struct Visualizer::VisualizerPimpl #elif defined(__APPLE__) id m_windowId; #elif defined(__linux__) - Window m_windowId; + void* m_windowId; // Pointer to either wl_surface* or X11 Window #endif #endif @@ -505,8 +508,28 @@ bool Visualizer::init(const VisualizerOptions &visualizerOptions) pimpl->m_windowId = glfwGetCocoaWindow(pimpl->m_window); irrDevParams.WindowId = (void*)(pimpl->m_windowId); #elif defined(__linux__) - pimpl->m_windowId = glfwGetX11Window(pimpl->m_window); - irrDevParams.WindowId = (void*)(pimpl->m_windowId); + + void* nativeWindow = nullptr; + + #ifdef IDYNTREE_GLFW_TRY_WAYLAND_FIRST + // Try Wayland first + struct wl_surface* waylandWindow = glfwGetWaylandWindow(pimpl->m_window); + #else + void* waylandWindow = nullptr; + #endif + + if (waylandWindow) + { + nativeWindow = static_cast<void*>(waylandWindow); + } + else + { + // Fallback to X11 + Window x11Window = glfwGetX11Window(pimpl->m_window); + if (x11Window) + nativeWindow = static_cast<void*>(reinterpret_cast<void*>(x11Window)); + } + irrDevParams.WindowId = nativeWindow; #endif irrDevParams.DeviceType = irr::EIDT_SDL;