1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-08 23:44:19 +00:00

Backends: GLFW: Load X11 functions dynamically to avoid x11 linking requirement. (#9116, #9109)

Amend 6b2cdf2 (#8884, #8474, #8289)
This commit is contained in:
Dario Mylonopoulos 2025-12-09 18:13:59 +01:00 committed by ocornut
parent ca46e5d959
commit 84a9d532b6
6 changed files with 55 additions and 11 deletions

View file

@ -32,6 +32,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-01-18: [Docking] Dynamically load X11 functions to avoid -lx11 linking requirement introduced on 2025-09-10.
// 2025-12-12: Added IMGUI_IMPL_GLFW_DISABLE_X11 / IMGUI_IMPL_GLFW_DISABLE_WAYLAND to forcefully disable either.
// 2025-12-10: Avoid repeated glfwSetCursor()/glfwSetInputMode() calls when unnecessary. Lowers overhead for very high framerates (e.g. 10k+ FPS).
// 2025-11-06: Lower minimum requirement to GLFW 3.0. Though a recent version e.g GLFW 3.4 is highly recommended.
@ -147,6 +148,7 @@
#ifndef GLFW_EXPOSE_NATIVE_X11 // for glfwGetX11Display(), glfwGetX11Window() on Freedesktop (Linux, BSD, etc.)
#define GLFW_EXPOSE_NATIVE_X11
#include <X11/Xatom.h>
#include <dlfcn.h> // for dlopen()
#endif
#include <GLFW/glfw3native.h>
#undef Status // X11 headers are leaking this.
@ -215,6 +217,13 @@ enum GlfwClientApi
GlfwClientApi_Unknown, // Anything else fits here.
};
#if GLFW_HAS_X11
typedef Atom (*PFN_XInternAtom)(Display*, const char* ,Bool);
typedef int (*PFN_XChangeProperty)(Display*, Window, Atom, Atom, int, int, const unsigned char*, int);
typedef int (*PFN_XChangeWindowAttributes)(Display*, Window, unsigned long, XSetWindowAttributes*);
typedef int (*PFN_XFlush)(Display*);
#endif
// GLFW data
struct ImGui_ImplGlfw_Data
{
@ -252,6 +261,15 @@ struct ImGui_ImplGlfw_Data
WNDPROC PrevWndProc;
#endif
#if GLFW_HAS_X11
// Module and function pointers loaded at initialization to avoid linking statically with X11.
void* X11Module;
PFN_XInternAtom XInternAtom;
PFN_XChangeProperty XChangeProperty;
PFN_XChangeWindowAttributes XChangeWindowAttributes;
PFN_XFlush XFlush;
#endif
ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@ -792,6 +810,26 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
#endif
#if GLFW_HAS_X11
if (!bd->IsWayland)
{
// Load X11 module dynamically. Copied from the way that GLFW does it in x11_init.c
#if defined(__CYGWIN__)
const char* x11_module_path = "libX11-6.so";
#elif defined(__OpenBSD__) || defined(__NetBSD__)
const char* x11_module_path = "libX11.so";
#else
const char* x11_module_path = "libX11.so.6";
#endif
bd->X11Module = dlopen(x11_module_path, RTLD_LAZY | RTLD_LOCAL);
bd->XInternAtom = (PFN_XInternAtom)dlsym(bd->X11Module, "XInternAtom");
bd->XChangeProperty = (PFN_XChangeProperty)dlsym(bd->X11Module, "XChangeProperty");
bd->XChangeWindowAttributes = (PFN_XChangeWindowAttributes)dlsym(bd->X11Module, "XChangeWindowAttributes");
bd->XFlush = (PFN_XFlush)dlsym(bd->X11Module, "XFlush");
IM_ASSERT(bd->XInternAtom != nullptr && bd->XChangeProperty != nullptr && bd->XChangeWindowAttributes != nullptr && bd->XFlush != nullptr);
}
#endif
// Emscripten: the same application can run on various platforms, so we detect the Apple platform at runtime
// to override io.ConfigMacOSXBehaviors from its default (which is always false in Emscripten).
#ifdef __EMSCRIPTEN__
@ -855,6 +893,11 @@ void ImGui_ImplGlfw_Shutdown()
bd->PrevWndProc = nullptr;
#endif
#if GLFW_HAS_X11
if (bd->X11Module != nullptr)
dlclose(bd->X11Module);
#endif
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport);
@ -1272,20 +1315,20 @@ static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int)
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__EMSCRIPTEN__) && GLFW_HAS_GETPLATFORM
#define IMGUI_GLFW_HAS_SETWINDOWFLOATING
static void ImGui_ImplGlfw_SetWindowFloating(GLFWwindow* window)
static void ImGui_ImplGlfw_SetWindowFloating(ImGui_ImplGlfw_Data* bd, GLFWwindow* window)
{
#ifdef GLFW_EXPOSE_NATIVE_X11
if (glfwGetPlatform() == GLFW_PLATFORM_X11)
{
Display* display = glfwGetX11Display();
Window xwindow = glfwGetX11Window(window);
Atom wm_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
Atom wm_type_dialog = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
XChangeProperty(display, xwindow, wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&wm_type_dialog, 1);
Atom wm_type = bd->XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
Atom wm_type_dialog = bd->XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
bd->XChangeProperty(display, xwindow, wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&wm_type_dialog, 1);
XSetWindowAttributes attrs;
attrs.override_redirect = False;
XChangeWindowAttributes(display, xwindow, CWOverrideRedirect, &attrs);
XFlush(display);
bd->XChangeWindowAttributes(display, xwindow, CWOverrideRedirect, &attrs);
bd->XFlush(display);
}
#endif // GLFW_EXPOSE_NATIVE_X11
#ifdef GLFW_EXPOSE_NATIVE_WAYLAND
@ -1322,7 +1365,7 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
ImGui_ImplGlfw_ContextMap_Add(vd->Window, bd->Context);
viewport->PlatformHandle = (void*)vd->Window;
#ifdef IMGUI_GLFW_HAS_SETWINDOWFLOATING
ImGui_ImplGlfw_SetWindowFloating(vd->Window);
ImGui_ImplGlfw_SetWindowFloating(bd, vd->Window);
#endif
#ifdef _WIN32
viewport->PlatformHandleRaw = glfwGetWin32Window(vd->Window);

View file

@ -185,6 +185,8 @@ Docking+Viewports Branch:
gamepad/keyboard to move a window to another viewport. (#9053) [@lut0pia, @ocornut]
- Fixed implicit/fallback "Debug" window from staying visible if once docked. (#9151)
- Backends:
- GLFW: dynamically load X11 functions to avoid -lx11 linking requirement introduced
in 1.92.3. (#9116, #9109) [@ramenguy99]
- SDL2, SDL3: adjust IME offset to match other backends and master branch. (#6071, #1953)
- Win32: viewports created by backend forcefully direct messages to
DefWindowProcW() in order to support Unicode text input. (#9099, #3653, #5961) [@ulhc]

View file

@ -33,7 +33,7 @@ LIBS =
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += $(LINUX_GL_LIBS) -lX11 `pkg-config --static --libs glfw3`
LIBS += $(LINUX_GL_LIBS) `pkg-config --static --libs glfw3`
CXXFLAGS += `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)

View file

@ -41,7 +41,7 @@ LIBS =
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += $(LINUX_GL_LIBS) -lX11 `pkg-config --static --libs glfw3`
LIBS += $(LINUX_GL_LIBS) `pkg-config --static --libs glfw3`
CXXFLAGS += `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)

View file

@ -36,7 +36,6 @@ find_package(Vulkan REQUIRED)
#NAMES vulkan vulkan-1)
#set(LIBRARIES "glfw;${VULKAN_LIBRARY}")
set(LIBRARIES "glfw;Vulkan::Vulkan")
# FIXME: Linux needs linking with "X11" as well?
# Use vulkan headers from glfw:
include_directories(${GLFW_DIR}/deps)

View file

@ -33,7 +33,7 @@ LIBS =
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += $(LINUX_GL_LIBS) -lX11 `pkg-config --static --libs glfw3 vulkan`
LIBS += $(LINUX_GL_LIBS) `pkg-config --static --libs glfw3 vulkan`
CXXFLAGS += `pkg-config --cflags glfw3 vulkan`
CFLAGS = $(CXXFLAGS)