Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLFW3.4+ on X11: copy the WM_CLASS property from the parent window for viewports #8474

Open
wants to merge 1 commit into
base: docking
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions backends/imgui_impl_glfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,21 @@
#define GLFW_EXPOSE_NATIVE_WIN32
#endif
#include <GLFW/glfw3native.h> // for glfwGetWin32Window()
#endif
#ifdef __APPLE__
#elif defined(__APPLE__)
#ifndef GLFW_EXPOSE_NATIVE_COCOA
#define GLFW_EXPOSE_NATIVE_COCOA
#endif
#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
#elif !defined(__EMSCRIPTEN__)
// Freedesktop(Linux, BSD, etc)
#ifndef GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_X11
#include <X11/Xatom.h>
#endif
#ifndef GLFW_EXPOSE_NATIVE_WAYLAND
#define GLFW_EXPOSE_NATIVE_WAYLAND
#endif
#include <GLFW/glfw3native.h> // For getting the X11/Wayland window
#endif
#ifndef _WIN32
#include <unistd.h> // for usleep()
Expand Down Expand Up @@ -1114,6 +1123,60 @@ static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int)
}
}

#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__EMSCRIPTEN__) && (GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4))
static void ImGui_ImplGlfw_SetWindowIDFreedesktop(GLFWwindow* root)
{
// Should resolve issues where applications that utilise the viewports that have not set a WM_CLASS/WM_INSTANCE/xdg_toplevel
// application ID are shown incorrectly in desktop menus on freedesktop systems.
//
// CAUTION: Only really supports X11 right now!
//
// Gets the WM_CLASS and WM_INSTANCE properties from the root application X11 window and sets them for every viewport window.
//
// The major issue with this implementation is that as of now it's X11-specific. Scroll to the next comment to learn
// more about this.
#ifdef GLFW_EXPOSE_NATIVE_X11
if (glfwGetPlatform() == GLFW_PLATFORM_X11)
{
const auto display = glfwGetX11Display();
const auto window = glfwGetX11Window(root);

const Atom wmClassAtom = XInternAtom(display, "WM_CLASS", False);
Atom actualAtom;
int format;
unsigned long n, bytesAfter;
unsigned char* prop = NULL;

if (XGetWindowProperty(display, window, wmClassAtom, 0, 1024, False, XA_STRING, &actualAtom, &format, &n, &bytesAfter, &prop) == Success && prop)
{
// These 2 strings are packed into 1 string with 2 null terminators. Weird, I know
const char* instance = (char*)prop;
const char* className = instance + strlen(instance) + 1;

glfwWindowHintString(GLFW_X11_CLASS_NAME, className);
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, instance);

XFree(prop);
}
}
#endif

#ifdef GLFW_EXPOSE_NATIVE_WAYLAND
// TODO: HELP NEEDED! NOT IMPLEMENTED! Periodically check if the statements below are true
// Explanation: GLFW always sets some type of WM_CLASS or WM_INSTANCE on X11, however on Wayland it seems that it
// does not set any value, unless we tell it to. Given that child windows inherit window hints of parent windows,
// this means that parents and any subsequent windows have the same app ID of "". This means that they(should) be
// grouped correctly, however applications which do not set the app ID manually for their root window will not be
// able to take advantage of features of their desktop that require app IDs, including users being able to
// configure their behaviour in the window manager settings!
//
// And why is this not implemented? It might be impossible in the scope of dear imgui, or at least I do not know
// how to implement it. From what I found, the current xdg_toplevel interface does not support a way to get the app
// ID of a window in a non-compositor-specific manner
#endif
}
#endif

static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
Expand All @@ -1137,6 +1200,9 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
glfwWindowHint(GLFW_FLOATING, (viewport->Flags & ImGuiViewportFlags_TopMost) ? true : false);
#endif
GLFWwindow* share_window = (bd->ClientApi == GlfwClientApi_OpenGL) ? bd->Window : nullptr;
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__EMSCRIPTEN__) && (GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4))
ImGui_ImplGlfw_SetWindowIDFreedesktop(bd->Window);
#endif
vd->Window = glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", nullptr, share_window);
vd->WindowOwned = true;
viewport->PlatformHandle = (void*)vd->Window;
Expand Down
2 changes: 1 addition & 1 deletion examples/example_glfw_opengl2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ LIBS =

ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += -lGL `pkg-config --static --libs glfw3`
LIBS += -lGL -lX11 `pkg-config --static --libs glfw3`

CXXFLAGS += `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)
Expand Down
2 changes: 1 addition & 1 deletion examples/example_glfw_opengl3/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ LIBS =

ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += $(LINUX_GL_LIBS) `pkg-config --static --libs glfw3`
LIBS += $(LINUX_GL_LIBS) -lX11 `pkg-config --static --libs glfw3`

CXXFLAGS += `pkg-config --cflags glfw3`
CFLAGS = $(CXXFLAGS)
Expand Down
2 changes: 1 addition & 1 deletion examples/example_glfw_vulkan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ find_package(Vulkan REQUIRED)
#find_library(VULKAN_LIBRARY
#NAMES vulkan vulkan-1)
#set(LIBRARIES "glfw;${VULKAN_LIBRARY}")
set(LIBRARIES "glfw;Vulkan::Vulkan")
set(LIBRARIES "glfw;Vulkan::Vulkan;X11")

# Use vulkan headers from glfw:
include_directories(${GLFW_DIR}/deps)
Expand Down