imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Multiple contexts/windows affecting each other's viewport/input/window coordinates

Open smurkel opened this issue 1 year ago • 5 comments

Multiple contexts/windows affecting each other's viewport/input/window coordinates

Dear ImGui 1.82 (18200) sizeof(size_t): 8, sizeof(ImDrawIdx): 4, sizeof(ImDrawVert): 20 define: __cplusplus=199711 define: _WIN32 define: _WIN64 define: _MSC_VER=1924 define: _MSVC_LANG=201402 define: IMGUI_HAS_VIEWPORT define: IMGUI_HAS_DOCK io.BackendPlatformName: NULL io.BackendRendererName: NULL io.ConfigFlags: 0x00000040 DockingEnable io.ConfigViewportsNoDecoration io.ConfigInputTextCursorBlink io.ConfigMemoryCompactTimer = 60.0 io.BackendFlags: 0x00000000 io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64 io.DisplaySize: 1100.00,700.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

Back-end/Renderer/Compiler/OS

Operating System: Windows 10.0.19044

My Issue/Question:

Hi all,

I'm using imgui via the pyimgui-wheels Python module (https://github.com/pyimgui/pyimgui) but since that repo is not very active and I believe this issue is imgui itself and not in the python wrapper (the python module just provides calls the imgui c++ library) I am posting here. I am also not sure whether my problem is due to a bug or a mistake I am making, but I am starting to feel it is a bug.

The problem is as follows: I have two glfw windows, A and B, with each their own imgui context. Window A is made first, then the imgui context is set up for it, then window B is made and the imgui context for it is set up, using a font atlas pointer grabbed from imgui context A. When glfw window A is resized, imgui windows in window B move. It seems that the (imgui?) viewport in window B is also resized when I resize glfw window A.

Using the imgui metrics window I found out that both contexts have one imgui viewport each. These viewports are both called 'Viewport #0' and have the same ID (0x11111111), parent (0x00000000) and Window ("N/A") but they do have a different size: (1100, 700) for (glfw) window A, and (600, 700) for window B, which is the size I set for the glfw window upon making them. When I change the size of glfw window A, the viewport of imgui context A changes in size accordingly while that of context B is not affected. However, when I make viewport A smaller in size than viewport B, imgui graphics in window B are clipped to the size of viewport A. Moreover, when I change the height of glfw window B, the imgui cursor position if offset w.r.t the actual on screen cursor position. Meanwhile in window A everything is behaving as it should.

After making the glfw windows, I set imgui up like this:

[make glfw_window_a] glfw.make_window_current(glfwwindow_a) imgui_context_a = imgui.create_context() imgui_impl_a= GlfwRenderer(glfwwindow_a) [set glfwwindow_a callbacks, etc., including glfw.set_window_size_callback(...), not sure if relevant]

[make glfw_window_b] glfw.make_window_current(glfwwindow_b) imgui_context_b = imgui.create_context(imgui_impl_a.io.fonts) imgui_impl_b = GlfwRenderer(glfw_window_b) [set glfwwindow_b callbacks, etc., including glfw.set_window_size_callback(...), not sure if relevant]

Then in the main loop:

imgui.set_current_context(imgui_context_a) imgui.new_frame() [gui for window a, and other app-specific things] imgui.render() imgui_impl_a.render(imgui.get_draw_data())

imgui.set_current_context(imgui_context_b) imgui_impl_b.refresh_font_texture() imgui.new_frame() [gui for window b, and other app-specific things] imgui.render() imgui_impl_b.render(imgui.get_draw_data())

Standalone, minimal, complete and verifiable example:

I'm hoping the above description is sufficient to ring a bell with someone, if not I will set up a minimal example.

smurkel avatar Sep 10 '22 14:09 smurkel

Dear ImGui 1.82 is quite old. That version of the GLFW backend doesn't support multiple contexts at all, and even in the latest version it's not well supported:

https://github.com/ocornut/imgui/blob/cb48c81a448aa0a4867e327c0a045a708ff3842e/backends/imgui_impl_glfw.cpp#L116-L119

As an aside, is there a reason you're using the multi-viewports/docking branch and multiple contexts at the same time?

PathogenDavid avatar Sep 10 '22 17:09 PathogenDavid

Ah, right. I'd noticed issues with the callbacks before but worked my way around that a little bit. Thanks for your response. I'm using the docking branch (but without using any docking features) simply because it's the imgui branch used in the most recent version of pyimgui. (or at least so I thought - I was looking in to other forks of pyimgui just now and saw there are some updated ones, but none that seem particularly farther ahead). I decided to go for multiple windows rather than one main window + docking imgui panels because the app I'm working on consists of two main but distinct interfaces: i) a window to inspect data, with some other OpenGL rendering things going on and some imgui control panels, and ii) a window in which the data processing pipeline is set up graphically. I wasn't sure how I was going to make the app so that the user could have two (windowed) full screen windows on different monitors, and to use docking at the same time. I'll try for a bit longer to find a workaround for this issue, if I succeed I'll post it later in case anyone else encounters the same thing.

smurkel avatar Sep 10 '22 21:09 smurkel

I don't know if this will help but I experienced something like this but with SDL and C++. I suspect that wherever your window events are handled, all of the events are being sent to the window A imgui context. I haven't used imgui with python but in C++ I fixed it by reading all the window events and checking if they were meant for each window and then invoking the backend function to send events to imgui. Additionally I had to requeue the window events that weren't used on that window so the other window could receive the window events that were meant for it. See my comment at the end of issue #4983 to see how I fixed it. Hope it helps!

tomasguillen avatar Oct 02 '22 00:10 tomasguillen

Thanks for the suggestion! I haven't been able to fix the problem yet, so next time I look in to it I will try out your fix.

smurkel avatar Oct 03 '22 13:10 smurkel

Maybe this post is useful to someone in the future.

Solution: it's on the first page of the documentation for pyimgui but somehow I had never noticed this... manually setting the display size prior to every imgui.new_frame() call works to fix the issue. (I think I always assumed that this would be done internally since the imgui implementation is coupled to a glfw window but apparently not.) (docs at: https://pyimgui.readthedocs.io/en/latest/guide/first-steps.html)

So instead of: imgui.set_current_context(imgui_context_a) imgui.new_frame() [gui for window a, and other app-specific things] imgui.render() imgui_impl_a.render(imgui.get_draw_data()) etc.

Code is now: imgui.set_current_context(imgui_context_a) imgui.get_io().display_size = self.window.width, self.window.height imgui.new_frame() [gui for window a, and other app-specific things] imgui.render() imgui_impl_a.render(imgui.get_draw_data()) etc.

smurkel avatar Dec 31 '22 14:12 smurkel