From d7ed8826253942934c4eda2538c8829315bd40e3 Mon Sep 17 00:00:00 2001 From: lgulich <22480644+lgulich@users.noreply.github.com> Date: Wed, 7 Oct 2026 21:13:35 +0200 Subject: [PATCH] Prefer GLFW X11 backend when no Wayland display is set (#11) GLFW >= 3.4 built with both Wayland and X11 probes Wayland first when XDG_SESSION_TYPE is unset, so inside Docker libwayland prints "error: XDG_RUNTIME_DIR is invalid or not set in the environment." before GLFW falls back to X11. Hint the X11 platform before every glfwInit() (viewer and camera plugin, which can each carry their own statically linked GLFW) when WAYLAND_DISPLAY is unset. Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 0c75738f32a5a53f17664ad1c44109bf8c7b6e06) --- mujoco_ros2_control/src/mujoco_simulation.cpp | 3 ++ .../glfw_platform.hpp | 42 +++++++++++++++++++ .../src/camera_plugin.cpp | 3 ++ 3 files changed, 48 insertions(+) create mode 100644 mujoco_ros2_control_plugins/include/mujoco_ros2_control_plugins/glfw_platform.hpp diff --git a/mujoco_ros2_control/src/mujoco_simulation.cpp b/mujoco_ros2_control/src/mujoco_simulation.cpp index fc3f058c..965853b2 100644 --- a/mujoco_ros2_control/src/mujoco_simulation.cpp +++ b/mujoco_ros2_control/src/mujoco_simulation.cpp @@ -20,6 +20,7 @@ #include "mujoco_ros2_control/mujoco_simulation.hpp" #include "array_safety.h" #include "mujoco_ros2_control/sim_display_text.hpp" +#include "mujoco_ros2_control_plugins/glfw_platform.hpp" #include #include @@ -555,6 +556,8 @@ bool MujocoSimulation::initialize(rclcpp::Node::SharedPtr node, const std::strin sim_speed_factor_ = sim_speed_factor; headless_ = headless; + mujoco_ros2_control_plugins::prefer_x11_without_wayland_display(); + if (sim_speed_factor_ > 0) { RCLCPP_INFO(get_logger(), "Running the simulation at %.2f percent speed", sim_speed_factor_ * 100.0); diff --git a/mujoco_ros2_control_plugins/include/mujoco_ros2_control_plugins/glfw_platform.hpp b/mujoco_ros2_control_plugins/include/mujoco_ros2_control_plugins/glfw_platform.hpp new file mode 100644 index 00000000..dd9f068d --- /dev/null +++ b/mujoco_ros2_control_plugins/include/mujoco_ros2_control_plugins/glfw_platform.hpp @@ -0,0 +1,42 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef MUJOCO_ROS2_CONTROL_PLUGINS__GLFW_PLATFORM_HPP_ +#define MUJOCO_ROS2_CONTROL_PLUGINS__GLFW_PLATFORM_HPP_ + +#include + +#include + +namespace mujoco_ros2_control_plugins +{ + +/** + * GLFW >= 3.4 built with both Wayland and X11 probes Wayland first unless XDG_SESSION_TYPE says otherwise. Without + * a Wayland compositor (e.g. inside Docker) libwayland prints "XDG_RUNTIME_DIR is invalid or not set" before GLFW + * falls back to X11. Skip the probe when no Wayland display is advertised. Must run before glfwInit(). + * + * Static so that each shared library calls the GLFW it links against; a statically linked GLFW has per-library state. + */ +static inline void prefer_x11_without_wayland_display() +{ +#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4) + if (std::getenv("WAYLAND_DISPLAY") == nullptr && glfwPlatformSupported(GLFW_PLATFORM_X11)) + { + glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11); + } +#endif +} + +} // namespace mujoco_ros2_control_plugins + +#endif // MUJOCO_ROS2_CONTROL_PLUGINS__GLFW_PLATFORM_HPP_ diff --git a/mujoco_ros2_control_plugins/src/camera_plugin.cpp b/mujoco_ros2_control_plugins/src/camera_plugin.cpp index 3a20e2f9..2e1f38da 100644 --- a/mujoco_ros2_control_plugins/src/camera_plugin.cpp +++ b/mujoco_ros2_control_plugins/src/camera_plugin.cpp @@ -19,6 +19,8 @@ #include "camera_plugin.hpp" +#include "mujoco_ros2_control_plugins/glfw_platform.hpp" + namespace mujoco_ros2_control_plugins { @@ -51,6 +53,7 @@ bool CameraPlugin::init(rclcpp::Node::SharedPtr node, const mjModel* model, mjDa // Start the rendering thread process // Try GLFW first, fall back to EGL for headless environments + prefer_x11_without_wayland_display(); if (glfw_init_fn()) { use_egl_ = false;