imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Easier identification of ImGui windows on X11

Open Ikos3k opened this issue 1 year ago • 4 comments

Version/Branch of Dear ImGui:

Version 1.91.7 WIP, Branch: docking

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Linux i3wm (x11)

Full config/build information:

Dear ImGui 1.91.7 WIP (19163)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=201703
define: __linux__
define: __GNUC__=14
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_glfw
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000480
 DockingEnable
 ViewportsEnable
io.ConfigViewportsNoDecoration
io.ConfigNavCaptureKeyboard
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001C0E
 HasMouseCursors
 HasSetMousePos
 PlatformHasViewports
 HasMouseHoveredViewport
 RendererHasVtxOffset
 RendererHasViewports
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,128
io.DisplaySize: 800.00,600.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

Details:

My Issue: Managing ImGui windows under i3wm (or other tiling window managers) is problematic because all ImGui windows either lack sufficient unique identifiers or share a generic WM_CLASS property. This limitation makes it difficult to apply specific window management rules, such as automatically enabling floating mode for docked ImGui windows. For example, in i3wm’s configuration file, users would like to apply a rule like: for_window [class="ImGui"] floating enable for_window [instance="ImGui"] floating enable

Proposed Solution: ImGui could set a custom WM_CLASS property or another identifier for their windows on X11, allowing for easier and more precise window management in tiling window managers like i3wm.

Screenshots/Video:

image

https://github.com/user-attachments/assets/a2a6bede-3709-49de-bf81-f8ddc72e024a

xprop output of ImGui docked window: image

Minimal, Complete and Verifiable Example code:

ImGui::Begin("Example Bug");
ImGui::End();

Ikos3k avatar Jan 03 '25 22:01 Ikos3k

Hello, I don't know how to implement this but it would be great it would largely help with #2117 A PR would be welcome.

ocornut avatar Jan 06 '25 11:01 ocornut

I might have a clue to how we can implement it. Might also make a PR if we decided we want to include this functionality into dear imgui.

On X11 there is the WM_CLASS property. On Wayland there is an app ID, which is also a string. These variables are used as application IDs, rather than window IDs. This is because if an application spawns a child window, the child window should still be identified as part of the base application.

This means that we should be setting the same app ID for both the origin and all workspace windows, in order for them to be grouped correctly. However, what I can't really wrap my head around is whether we need to actually give unique identifiers to these child windows, and if we have to, how do we do it? To be honest, from what I know the task of remembering the position of a window is performed by the Session manager/Window manager so maybe setting some type of unique ID might help the session manager remember the window positions from the previous session. I might be overthinking it though, so it's best I research this.

As a side note, this is really useful for a lot of use-cases, specifically the way desktop environments manage taskbar icons. Though there is a way to set the application icon on X11/Wayland, many desktop environments ignore it in favour of using the icon from the application's desktop file. So an example application will first need to have a desktop entry like this:

[Desktop Entry]
Type=Application
Version=1.0
Name=example
Icon=example-icon
TryExec=example
Exec=example
StartupWMClass=example

with the StartupWMClass field set to the application ID, and then when launched it should register its application ID with the windowing system.

Anyway, these strings are set by the backend. For example, here is an X11/Wayland compatible way to set your Window ID in glfw, which I use in one of my applications:

#ifdef GLFW_PLATFORM_X11
    glfwWindowHintString(GLFW_X11_CLASS_NAME, applicationName.c_str());
#endif
#ifdef GLFW_PLATFORM_WAYLAND
    glfwWindowHintString(GLFW_WAYLAND_APP_ID, applicationName.c_str());
#endif

So the easiest solution would be to create a string field for such an ID in the backends configuration for GLFW, SDL2 and SDL3. There are a couple of questions that still stand, however:

  1. We need to check how workspaces behave in these 3 backends, and whether we have to do something more for them to inherit the application ID for every child window
  2. We need to do additional testing to see if we need to set any unique identifiers for each child window and try to think of an API to set them(might be needed for remembering window position from previous sessions)
  3. We need to also consider whether this should actually included in dear imgui? Should part of this code be part of the third party backend libraries instead? What should and should not be set by dear imgui?

I will return with the required research on points 1 and 2 as soon as possible.

Madman10K avatar Feb 04 '25 02:02 Madman10K

Hello, I forgot about this issue, sorry about that 😅

Anyway, so I found out that:

  1. SDL automatically sets the application ID to the name of the executable by default. GLFW sets the WM class to the title of the window by default, which is why viewports have a different WM class than the normal window imgui_impl_glfw.cpp L1133
  2. For session management:
    • On X11, it looks like the window position is remembered automatically by the session manager for both libraries
    • I did not test on Wayland
  3. Child windows are treated as regular windows in both libraries.

It looks like SDL and GLFW work in the same way, though they use different defaults. So we can try to just copy the application ID of the parent window in the GLFW backend. It also needs to be checked, whether child windows inherit the application ID of the parent if the application ID is changed manually for it. This is so we know whether to also include this functionality in SDL.

Everything else is simply implementation details on how to actually copy the IDs 🙂

Madman10K avatar Feb 22 '25 18:02 Madman10K

Hello, turns out children inherit the window IDs of the parents when set manually in both GLFW and SDL so at least only the GLFW backend needs to be changed for the case where no such ID is set.

However, the situation with GLFW is complicated:

  1. There is no way to get the data from GLFW window hints so we have to implement those 2 hints ourselves using the native API. Should be easy enough on X11 at least.
  2. The code I used as an example is not entirely correct. Turns out an additional string hint of GLFW_X11_INSTANCE_NAME is also required in order to set the WM_CLASS property correctly on X11. This is outlined on the ICCCM documentation. This field can also be set to any string, though the general convention seems to be that most applications set it to the name of their binary. So maybe that's what we need to do(not ideal, since this requires some OS-specific code 🥲)

To save ourselves interacting with the OS, I think the best solution might be to store the application ID and instance ID strings ourselves for the GLFW backend. A utility function(part of the GLFW backend) can then be made that can be used to set these 2 IDs correctly for the parent window and every child window after that. The documentation and examples can then be updated to use this utility function so that new users start off with the best possible configuration.

Any opinion on whether this is a good way to implement this feature in a further PR or should another design be considered?

Madman10K avatar Feb 24 '25 01:02 Madman10K

As per merged #8884 let me know what you think we should be doing with this discussion. It is worth keeping open?

ocornut avatar Sep 10 '25 18:09 ocornut