Skip to content

Commit 664ee06

Browse files
committed
platform(X11): set WM_CLASS and WM_INSTANCE for viewport windows appropriately
1 parent 19d060c commit 664ee06

File tree

4 files changed

+71
-5
lines changed

4 files changed

+71
-5
lines changed

backends/imgui_impl_glfw.cpp

+68-2
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,21 @@
112112
#define GLFW_EXPOSE_NATIVE_WIN32
113113
#endif
114114
#include <GLFW/glfw3native.h> // for glfwGetWin32Window()
115-
#endif
116-
#ifdef __APPLE__
115+
#elif defined(__APPLE__)
117116
#ifndef GLFW_EXPOSE_NATIVE_COCOA
118117
#define GLFW_EXPOSE_NATIVE_COCOA
119118
#endif
120119
#include <GLFW/glfw3native.h> // for glfwGetCocoaWindow()
120+
#elif !defined(__EMSCRIPTEN__)
121+
// Freedesktop(Linux, BSD, etc)
122+
#ifndef GLFW_EXPOSE_NATIVE_X11
123+
#define GLFW_EXPOSE_NATIVE_X11
124+
#include <X11/Xatom.h>
125+
#endif
126+
#ifndef GLFW_EXPOSE_NATIVE_WAYLAND
127+
#define GLFW_EXPOSE_NATIVE_WAYLAND
128+
#endif
129+
#include <GLFW/glfw3native.h> // For getting the X11/Wayland window
121130
#endif
122131
#ifndef _WIN32
123132
#include <unistd.h> // for usleep()
@@ -1114,6 +1123,60 @@ static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int)
11141123
}
11151124
}
11161125

1126+
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__EMSCRIPTEN__) && (GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4))
1127+
static void ImGui_ImplGlfw_SetWindowIDFreedesktop(GLFWwindow* root)
1128+
{
1129+
// Should resolve issues where applications that utilise the viewports that have not set a WM_CLASS/WM_INSTANCE/xdg_toplevel
1130+
// application ID are shown incorrectly in desktop menus on freedesktop systems.
1131+
//
1132+
// CAUTION: Only really supports X11 right now!
1133+
//
1134+
// Gets the WM_CLASS and WM_INSTANCE properties from the root application X11 window and sets them for every viewport window.
1135+
//
1136+
// The major issue with this implementation is that as of now it's X11-specific. Scroll to the next comment to learn
1137+
// more about this.
1138+
#ifdef GLFW_EXPOSE_NATIVE_X11
1139+
if (glfwGetPlatform() == GLFW_PLATFORM_X11)
1140+
{
1141+
const auto display = glfwGetX11Display();
1142+
const auto window = glfwGetX11Window(root);
1143+
1144+
const Atom wmClassAtom = XInternAtom(display, "WM_CLASS", False);
1145+
Atom actualAtom;
1146+
int format;
1147+
unsigned long n, bytesAfter;
1148+
unsigned char* prop = NULL;
1149+
1150+
if (XGetWindowProperty(display, window, wmClassAtom, 0, 1024, False, XA_STRING, &actualAtom, &format, &n, &bytesAfter, &prop) == Success && prop)
1151+
{
1152+
// These 2 strings are packed into 1 string with 2 null terminators. Weird, I know
1153+
const char* instance = (char*)prop;
1154+
const char* className = instance + strlen(instance) + 1;
1155+
1156+
glfwWindowHintString(GLFW_X11_CLASS_NAME, className);
1157+
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, instance);
1158+
1159+
XFree(prop);
1160+
}
1161+
}
1162+
#endif
1163+
1164+
#ifdef GLFW_EXPOSE_NATIVE_WAYLAND
1165+
// TODO: HELP NEEDED! NOT IMPLEMENTED! Periodically check if the statements below are true
1166+
// Explanation: GLFW always sets some type of WM_CLASS or WM_INSTANCE on X11, however on Wayland it seems that it
1167+
// does not set any value, unless we tell it to. Given that child windows inherit window hints of parent windows,
1168+
// this means that parents and any subsequent windows have the same app ID of "". This means that they(should) be
1169+
// grouped correctly, however applications which do not set the app ID manually for their root window will not be
1170+
// able to take advantage of features of their desktop that require app IDs, including users being able to
1171+
// configure their behaviour in the window manager settings!
1172+
//
1173+
// And why is this not implemented? It might be impossible in the scope of dear imgui, or at least I do not know
1174+
// how to implement it. From what I found, the current xdg_toplevel interface does not support a way to get the app
1175+
// ID of a window in a non-compositor-specific manner
1176+
#endif
1177+
}
1178+
#endif
1179+
11171180
static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
11181181
{
11191182
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
@@ -1137,6 +1200,9 @@ static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
11371200
glfwWindowHint(GLFW_FLOATING, (viewport->Flags & ImGuiViewportFlags_TopMost) ? true : false);
11381201
#endif
11391202
GLFWwindow* share_window = (bd->ClientApi == GlfwClientApi_OpenGL) ? bd->Window : nullptr;
1203+
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__EMSCRIPTEN__) && (GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4))
1204+
ImGui_ImplGlfw_SetWindowIDFreedesktop(bd->Window);
1205+
#endif
11401206
vd->Window = glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", nullptr, share_window);
11411207
vd->WindowOwned = true;
11421208
viewport->PlatformHandle = (void*)vd->Window;

examples/example_glfw_opengl2/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ LIBS =
3232

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

3737
CXXFLAGS += `pkg-config --cflags glfw3`
3838
CFLAGS = $(CXXFLAGS)

examples/example_glfw_opengl3/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ LIBS =
4141

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

4646
CXXFLAGS += `pkg-config --cflags glfw3`
4747
CFLAGS = $(CXXFLAGS)

examples/example_glfw_vulkan/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ find_package(Vulkan REQUIRED)
3535
#find_library(VULKAN_LIBRARY
3636
#NAMES vulkan vulkan-1)
3737
#set(LIBRARIES "glfw;${VULKAN_LIBRARY}")
38-
set(LIBRARIES "glfw;Vulkan::Vulkan")
38+
set(LIBRARIES "glfw;Vulkan::Vulkan;X11")
3939

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

0 commit comments

Comments
 (0)