Does GLFW implementation only handle one GLFWindow?


I have two GLFW Windows, each of them has its own ImGuiContext. Each window displays some ImGui widgets. For handling both windows I Just do a context swap both for ImGui and GLFW before displaying the rights ImGui widgets in each window:

// Events polling, new frame, widgets, render, ...

// Events polling, new frame, widgets, render, ...

This works, I have the right widgets displayed in the right window. However, in the ImGui GLFW Implementation (imgui_impl_glfw.h) there is no concept of context switching. Only one GLFWWindow* is stored, in a global variable called g_Window once and for all when calling ImGui_ImplGlfw_InitForOpenGL. If I call ImGui_ImplGlfw_InitForOpenGL for the second window, g_Window is overridden with the second GLFWWindow*. I don’t see any way to change the value of g_Window afterward in order to switch between my two windows.

This is annoying for example when ImGui_ImplGlfw_UpdateMousePosAndButtons() is called, because all the GLFW api calls are based on g_Window:

ImGuiIO& io = ImGui::GetIO();
/* ... */
const bool focused = glfwGetWindowAttrib(g_Window, GLFW_FOCUSED) != 0;

if (focused)
	if (io.WantSetMousePos)
		glfwSetCursorPos(g_Window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y);
		double mouse_x, mouse_y;
		glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
		io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);

ImGui::GetIO() will give me the right IO structure from the current ImGuiContext but g_Window will always be my second GLFW window (the last I created). Thus, my first window is never considered focused, and receive mouse coordinates corresponding to the second window. This gives a funny situation when I can only interact with the GUI of the first window from the second window.

There is a quick fix I can think of which is providing a switch context function in imgui_impl_glfw.h/.cpp:

void ImGui_ImplGlfw_SetWindow(GLFWwindow* window)
	g_Window = window;

This seems to work even if some other global variable in this file may have the same problem (callbacks, g_MouseJustPressed, …). The continuity of this solution would be to enclose all these global variables in a struct in the same manner as for ImGuiContext, hence providing a full context switching.

Is there a better solution that I missed? Maybe I can make some GLFW related code in my application to handle my two windows, passing mouse coordinates and events manually to ImGui. If it’s the way to go how should I do that? I would like to avoid modifying the ImGui code like I did to avoid having to merge my modifications in newer version of ImGui each time.

Thank you for your time.

We problably ought to refactor those back-ends somehow. The key would be to do it without affecting their readability too much.

However the general tendency was to go toward support single-context with multi-viewports rather than multiple-context each with a single viewport. So maybe the multi-viewport feature is more adequate to your needs?

Thank you for your answer.

Your work on the multi-viewports/docking branch is really promising. I will keep my modified GLFW backend allowing context switching as it is a simple working solution for the GLFW backend in the main branch. This solution would be too complex for the multi-viewport branch as the backends are way more complex, and pretty much useless as multi-viewports would be then the way to go as you said. So I’ll keep an eye on this and I’ll try to experiment it soon.

Looking into imgui_impl_glfw.cpp in the docking branch, it seems that there is no callbacks chaining on the additional GLFWWindow created (on the main GLFWWindow the user installed callbacks are saved and chained). Am I missing something? Is there a way to still have a custom mouse clicks/move callback on the created windows? I think doing the opposite, chaining my callbacks with the ImGui ones, would do it.