1
0
Fork 0
mirror of https://github.com/ocornut/imgui.git synced 2026-01-11 00:04:24 +00:00

Backends: GLFW: load X11 functions dynamically to remove requirement to link with x11

This commit is contained in:
Dario Mylonopoulos 2025-12-09 18:13:59 +01:00 committed by Dario Mylonopoulos
parent 6327b63064
commit debd37b0ba

View file

@ -119,10 +119,15 @@
#endif
// GLFW
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#define GLFW_HAS_X11_OR_WAYLAND 1
#if !defined(IMGUI_IMPL_GLFW_DISABLE_X11) && (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__))
#define GLFW_HAS_X11 1
#else
#define GLFW_HAS_X11_OR_WAYLAND 0
#define GLFW_HAS_X11 0
#endif
#if !defined(IMGUI_IMPL_GLFW_DISABLE_WAYLAND) && (defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__))
#define GLFW_HAS_WAYLAND 1
#else
#define GLFW_HAS_WAYLAND 0
#endif
#include <GLFW/glfw3.h>
#ifdef _WIN32
@ -136,10 +141,11 @@
#define GLFW_EXPOSE_NATIVE_COCOA
#endif
#include <GLFW/glfw3native.h>
#elif GLFW_HAS_X11_OR_WAYLAND
#elif GLFW_HAS_X11
#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>
#endif
#include <GLFW/glfw3native.h>
#undef Status // X11 headers are leaking this.
@ -208,6 +214,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
{
@ -244,6 +257,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)); }
};
@ -275,7 +297,7 @@ static void ImGui_ImplGlfw_ShutdownMultiViewportSupport();
// Functions
static bool ImGui_ImplGlfw_IsWayland()
{
#if !GLFW_HAS_X11_OR_WAYLAND
#if !GLFW_HAS_WAYLAND
return false;
#elif GLFW_HAS_GETPLATFORM
return glfwGetPlatform() == GLFW_PLATFORM_WAYLAND;
@ -784,6 +806,30 @@ 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);
IM_ASSERT(bd->XChangeProperty != nullptr);
IM_ASSERT(bd->XChangeWindowAttributes != nullptr);
IM_ASSERT(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__
@ -847,6 +893,12 @@ void ImGui_ImplGlfw_Shutdown()
bd->PrevWndProc = nullptr;
#endif
#if GLFW_HAS_X11
if (!bd->IsWayland) {
dlclose(bd->X11Module);
}
#endif
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport);
@ -1051,7 +1103,7 @@ static void ImGui_ImplGlfw_UpdateMonitors()
// - Some accessibility applications are declaring virtual monitors with a DPI of 0.0f, see #7902. We preserve this value for caller to handle.
float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
{
#if GLFW_HAS_X11_OR_WAYLAND
#if GLFW_HAS_WAYLAND
if (ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window))
if (bd->IsWayland)
return 1.0f;
@ -1068,7 +1120,7 @@ float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window)
float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor)
{
#if GLFW_HAS_X11_OR_WAYLAND
#if GLFW_HAS_WAYLAND
if (ImGui_ImplGlfw_IsWayland()) // We can't access our bd->IsWayland cache for a monitor.
return 1.0f;
#endif
@ -1090,7 +1142,7 @@ static void ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(GLFWwindow* window,
glfwGetFramebufferSize(window, &display_w, &display_h);
float fb_scale_x = (w > 0) ? (float)display_w / (float)w : 1.0f;
float fb_scale_y = (h > 0) ? (float)display_h / (float)h : 1.0f;
#if GLFW_HAS_X11_OR_WAYLAND
#if GLFW_HAS_WAYLAND
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(window);
if (!bd->IsWayland)
fb_scale_x = fb_scale_y = 1.0f;
@ -1255,20 +1307,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
@ -1305,7 +1357,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);