ocornut/imgui

Linux/Mac compatibility of multi-viewports

ocornut opened this issue · 89 comments

This is a thread for people to discuss Linux/Mac (and notably custom window managers under Linux) specific issues with the Viewport branch, mentioned in #1542.
I am not a Linux user so I hope users will come to a solution to make the various bindings compatible with window managers.

January 2019: Viewport and Docking branches have been merged to simplify maintainance. Use the 'docking' branch to test multi-viewports.

The discussions involving @Ylannl @ebachard, @s-ol, @Lecrapouille starts around here:
#1542 (comment)

s-ol commented

👍

For now I think we should focus separately on the issues with the GLFW and WM integrations I have been mostly posting about and the more subtle problems e.g. @ebachard has been seeing. I think we should focus on the latter as the GLFW stuff (window jitter) is likely a bit further from the imgui core itself and better fixed on a tangent.

I just gave the SDL demo another try on i3 and I noticed some more details, mostly related to the two ways I can interact with the windows; I can either use my WM shortcut to move and resize the windows (in my case hold the Meta key and left/right drag, lets call this WM-dragging/resizing) or I can let ImGui do it (left-drag an empty spot or titlebar, left drag window corner or edges; app-dragging/resizing).

I found the following:

  • When WM-resizing I can only grow windows - dragging in the shrink-direction doesn't affect the window size at all
  • When I WM-drag a window over the main viewport the drag is aborted and I have to pick the window up again to keep position it. This happens in the moment that the dragged window is contained completely inside the main viewport. When app-dragging the window the windows are not merged until the mouse is released (ideal behavior).

@ocornut If you want I can try to investigate concerning the segfaut I caught. I think this is not an issue concerning a particular architecture. I just call valgrind on the example_glfw_opengl3: I got:

==3237== Process terminating with default action of signal 11 (SIGSEGV)
==3237==  Access not within mapped region at address 0x0
==3237==    at 0x10B9A2: ImGui_ImplGlfw_GetWindowPos(ImGuiViewport*) (imgui_impl_glfw.cpp:477)
==3237==    by 0x128F91: ImGui::UpdateViewports() (imgui.cpp:7465)
==3237==    by 0x137431: ImGui::NewFrame() (imgui.cpp:3294)
==3237==    by 0x10B202: main (main.cpp:127)

Then I added some asserts:

static ImVec2 ImGui_ImplGlfw_GetWindowPos(ImGuiViewport* viewport)
{
    assert(NULL != viewport);
    ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
    assert(NULL != data);
    assert(NULL != data->Window);
    int x = 0, y = 0;
    glfwGetWindowPos(data->Window, &x, &y);
    return ImVec2((float)x, (float)y);
}

And I got Assertion `NULL != data' failed. I never tried rr but I'll give a try to know if it catches the bug https://rr-project.org/

@Lecrapouille
What is the value of viewport->ID ?

It is calling the handler when viewport->PlatformRequestMove was set, which is set in ImGui_ImplGlfw_WindowPosCallback() when the window is moved which means the platform window was created.

There is maybe a possibility this gets called during the frame after window destruction.
Could you add printf() logging in ImGui_ImplGlfw_CreateWindow, ImGui_ImplGlfw_DestroyWindow printing viewport->ID, viewport->PlatformHandle, viewport->PlatformUserData, etc. with a frame counter?

// and the bottom of ImGui_ImplGlfw_CreateWindow
printf("[%05d] CreateWindowID %08X\n", ImGui::GetFrameCount(), viewport->ID, viewport->PlatformHandle, viewport->PlatformUserData);
// at the top of ImGui_ImplGlfw_DestroyWindow
printf("[%05d] DestroyWindow ID %08X\n", ImGui::GetFrameCount(), viewport->ID, viewport->PlatformHandle, viewport->PlatformUserData);

In fact to produce the segfault there is an easier way: move the "hello world" window outside (partially) the main win (else this is not working) then just move up and down your mouse cursor on the blue box of clear color to pop up/down the color panel (which starts shaking), this is enough to produce the crash.

Forget for rr I cannot use it with AMD Ryzen :( So I'm using the printf method :

In static void ImGui::UpdateViewports() inside the loop I added:

printf("ImGuiViewportP* viewport = g.Viewports[%d]; %p    %p\n", n, viewport, viewport->PlatformUserData);

Also I added printf in:

IM_DELETE(viewport);
printf("IM_DELETE(viewport) %p  %p\n", viewport, viewport->PlatformUserData);
n--;

And finally inside static ImVec2 ImGui_ImplGlfw_GetWindowPos(ImGuiViewport* viewport)

For me the NULL pointer comes from this code:

static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport) { 
...
printf("Before ImGui_ImplGlfw_DestroyWindow %p  %p\n", viewport, viewport->PlatformUserData);
    viewport->PlatformUserData = viewport->PlatformHandle = NULL;
printf("After ImGui_ImplGlfw_DestroyWindow %p  %p\n", viewport, viewport->PlatformUserData);

With valgrind + printf I see that:

--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11914810    0x11918610
Before ImGui_ImplGlfw_DestroyWindow 0x11914810  0x11918610
After ImGui_ImplGlfw_DestroyWindow 0x11914810  (nil)
ImGui_ImplGlfw_GetWindowPos 0xf635380
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11914810    (nil)
ImGui_ImplGlfw_GetWindowPos 0xf635380
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11914810    (nil)
==27446== Invalid read of size 8
==27446==    at 0x1281D3: ImGui::UpdateViewports() (imgui.cpp:7458)
==27446==    by 0x1177D4: ImGui::NewFrame() (imgui.cpp:3294)
==27446==    by 0x10AB9B: main (main.cpp:127)
==27446==  Address 0x11914838 is 40 bytes inside a block of size 224 free'd
==27446==    at 0x4C2CDDB: free (vg_replace_malloc.c:530)
==27446==    by 0x10EAD6: FreeWrapper(void*, void*) (imgui.cpp:992)
==27446==    by 0x115684: ImGui::MemFree(void*) (imgui.cpp:2815)
==27446==    by 0x145BB4: void IM_DELETE<ImGuiViewportP>(ImGuiViewportP*) (imgui.h:1428)
==27446==    by 0x1281CE: ImGui::UpdateViewports() (imgui.cpp:7457)
==27446==    by 0x1177D4: ImGui::NewFrame() (imgui.cpp:3294)
==27446==    by 0x10AB9B: main (main.cpp:127)
==27446==  Block was alloc'd at
==27446==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==27446==    by 0x10EAB8: MallocWrapper(unsigned long, void*) (imgui.cpp:991)
==27446==    by 0x11562C: ImGui::MemAlloc(unsigned long) (imgui.cpp:2807)
==27446==    by 0x128720: ImGui::AddUpdateViewport(ImGuiWindow*, unsigned int, ImVec2 const&, ImVec2 const&, int) (imgui.cpp:7574)
==27446==    by 0x11F4BB: ImGui::Begin(char const*, bool*, int) (imgui.cpp:5179)
==27446==    by 0x125E59: ImGui::BeginTooltipEx(int, bool) (imgui.cpp:6890)
==27446==    by 0x1947FE: ImGui::ColorTooltip(char const*, float const*, int) (imgui_widgets.cpp:4486)
==27446==    by 0x1945CC: ImGui::ColorButton(char const*, ImVec4 const&, int, ImVec2) (imgui_widgets.cpp:4457)
==27446==    by 0x190FF1: ImGui::ColorEdit4(char const*, float*, int) (imgui_widgets.cpp:3932)
==27446==    by 0x190433: ImGui::ColorEdit3(char const*, float*, int) (imgui_widgets.cpp:3807)
==27446==    by 0x10AC42: main (main.cpp:145)
==27446== 

After some iterations we reach the assert:

ImGui_ImplGlfw_GetWindowPos 0x11a62280  (nil)
example_glfw_opengl3: ../imgui_impl_glfw.cpp:484: ImVec2 ImGui_ImplGlfw_GetWindowPos(ImGuiViewport*): Assertion `data != NULL' failed

@ocornut I did not see your comments when I wrote mine. I gonna try to answer you (I do not know well your code sorry)

note: >>> TRUE is when viewport->PlatformRequestMove = true;
1/

[00113] CreateWindowID 8C2D4FD5  (nil) (nil)
plat = data
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0x11518a60  0x1151c920
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    0x1151c920
[00129] DestroyWindow ID 8C2D4FD5 0x1151c970 0x1151c920
Before ImGui_ImplGlfw_DestroyWindow 0x11518a60  0x1151c920
After ImGui_ImplGlfw_DestroyWindow 0x11518a60  (nil)
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    (nil)
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x11518a60    (nil)
==27931== Invalid read of size 8
==27931==    at 0x12827B: ImGui::UpdateViewports() (imgui.cpp:7458)
==27931==    by 0x11787C: ImGui::NewFrame() (imgui.cpp:3294)
==27931==    by 0x10AB9B: main (main.cpp:127)
==27931==  Address 0x11518a88 is 40 bytes inside a block of size 224 free'd
==27931==    at 0x4C2CDDB: free (vg_replace_malloc.c:530)
==27931==    by 0x10EB7E: FreeWrapper(void*, void*) (imgui.cpp:992)
==27931==    by 0x11572C: ImGui::MemFree(void*) (imgui.cpp:2815)
==27931==    by 0x145C5C: void IM_DELETE<ImGuiViewportP>(ImGuiViewportP*) (imgui.h:1428)
==27931==    by 0x128276: ImGui::UpdateViewports() (imgui.cpp:7457)
==27931==    by 0x11787C: ImGui::NewFrame() (imgui.cpp:3294)
==27931==    by 0x10AB9B: main (main.cpp:127)
==27931==  Block was alloc'd at
==27931==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==27931==    by 0x10EB60: MallocWrapper(unsigned long, void*) (imgui.cpp:991)
==27931==    by 0x1156D4: ImGui::MemAlloc(unsigned long) (imgui.cpp:2807)
==27931==    by 0x1287C8: ImGui::AddUpdateViewport(ImGuiWindow*, unsigned int, ImVec2 const&, ImVec2 const&, int) (imgui.cpp:7574)
==27931==    by 0x11F563: ImGui::Begin(char const*, bool*, int) (imgui.cpp:5179)
==27931==    by 0x125F01: ImGui::BeginTooltipEx(int, bool) (imgui.cpp:6890)
==27931==    by 0x1948A6: ImGui::ColorTooltip(char const*, float const*, int) (imgui_widgets.cpp:4486)
==27931==    by 0x194674: ImGui::ColorButton(char const*, ImVec4 const&, int, ImVec2) (imgui_widgets.cpp:4457)
==27931==    by 0x191099: ImGui::ColorEdit4(char const*, float*, int) (imgui_widgets.cpp:3932)
==27931==    by 0x1904DB: ImGui::ColorEdit3(char const*, float*, int) (imgui_widgets.cpp:3807)
==27931==    by 0x10AC42: main (main.cpp:145)
==27931== 
IM_DELETE(viewport) 0x11518a60  (nil)
[00131] CreateWindowID 8C2D4FD5  (nil) (nil)
plat = data
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x117832c0    0x11785450
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x117832c0  0x11785450
ImGui_ImplGlfw_GetWindowPos 0x117832c0  0x11785450
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x117832c0    0x11785450
[00133] DestroyWindow ID 8C2D4FD5 0x117854a0 0x11785450
Before ImGui_ImplGlfw_DestroyWindow 0x117832c0  0x11785450
After ImGui_ImplGlfw_DestroyWindow 0x117832c0  (nil)
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0

then several cycles after:

********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x119910e0    0x119931b0
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x119910e0  0x119931b0
ImGui_ImplGlfw_GetWindowPos 0x119910e0  0x119931b0
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x119910e0    0x119931b0
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x119910e0    0x119931b0
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x119910e0  0x119931b0
ImGui_ImplGlfw_GetWindowPos 0x119910e0  0x119931b0
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x119910e0    0x119931b0
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x119910e0    0x119931b0
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x119910e0  0x119931b0
ImGui_ImplGlfw_GetWindowPos 0x119910e0  0x119931b0
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x119910e0    0x119931b0
********** ImGui_ImplGlfw_WindowPosCallback
>>> TRUE
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x119910e0    0x119931b0
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x119910e0  0x119931b0
ImGui_ImplGlfw_GetWindowPos 0x119910e0  0x119931b0
[00177] DestroyWindow ID 8C2D4FD5 0x11993200 0x119931b0
Before ImGui_ImplGlfw_DestroyWindow 0x119910e0  0x119931b0
After ImGui_ImplGlfw_DestroyWindow 0x119910e0  (nil)
ImGui_ImplGlfw_GetWindowPos 0xf635380  0xf6646a0
--------------------
ImGuiViewportP* viewport = g.Viewports[0]; 0xf635380    0xf6646a0
ImGuiViewportP* viewport = g.Viewports[1]; 0x104ed210    0x10503470
ImGuiViewportP* viewport = g.Viewports[2]; 0x119910e0    (nil)
g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable 0x119910e0  (nil)
ImGui_ImplGlfw_GetWindowPos 0x119910e0  (nil)
example_glfw_opengl3: ../imgui_impl_glfw.cpp:491: ImVec2 ImGui_ImplGlfw_GetWindowPos(ImGuiViewport*): Assertion `data != NULL failed.

For me the PlatformUserData is set to NULL in ImGui_ImplGlfw_DestroyWindow then used by ImGui_ImplGlfw_GetWindowPos and not dropped by UpdateViewports inside the for (int n = 0; n < g.Viewports.Size; n++)

PPS: tried to add && viewport->PlatformUserData != NULL to if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) this does not help stopping shaking windows :(

Sorry, I don't have much time these days, but I finaly found one hour, and tested the most recent code today. No time to track unfortunaly :-(

Quicly, my configuration is based on Linux Intel x86_64 (+ lot of RAM), HD 620 chipset, gcc-5.4.0 , Linux Mint 18.3 (customized 4.15.18 kernel for uvc 1.5 compatibility) / Gnome Environment
WM : default is compiz + Compton compositor + 3D effects, but I tested as well Metacity + Compton compositor, or Mutter + Compton or even Marco + Compton

What I observed:

Looks like the crash caused by the clear color window, overlaping the main SDL2 window or GLFW Window is not fixed : the crash is still there :-/

Probably a regression : using OpenGL3 + SDL2, or OpenGL3 + GLFW, whatever the WM, I see the following issue : when you drag one window outside the main window, the dragged window seems to flicker once overlaping the main window.

Other issue : when one obrder of the dragged window reaches the border of the screen, the flickering .is triggered

Maybe my imagination, but could there be a race condition between mouse coordinates and window coordinates? The simple trick to stop the ImGui Window to flicker, is to click somewhere inside the main SDL2 or GLFW window. Secondly, I remarked that the ImGui windows always tries to return at its original position, means at the point ( x ~ 50 pixels , y = 50 pixels ) from the Top Left of the main SDL or GLFW window.

Unfortunaly, I didn't make a backup of the previous sources. Got to catch with git to retrieve the old version.

Sorry, got to go. I hope I'll have more time at the end of the week.

HTH

EDIT : I wrongly wrote that the crash was fixed, but it is not in fact ...

For the record, I reproduced the crash with debug enabled, and as expected, there is some null window and coordinates somewhere:


[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff00fb700 (LWP 24553)]
[New Thread 0x7fffed9c9700 (LWP 24554)]

Thread 1 "example_sdl_ope" received signal SIGSEGV, Segmentation fault.
0x0000000000403cf5 in ImGui_ImplSDL2_GetWindowPos (viewport=0x456b320) at ../imgui_impl_sdl.cpp:433
433	    SDL_GetWindowPosition(data->Window, &x, &y);
(gdb) p x
$1 = 0
(gdb) p y
$2 = 0
(gdb) p data->Window
Cannot access memory at address 0x0

To reproduce the crash :

  1. compile the example_opengl3 with debug enabled ( -g option for g++ )

If you don't want to build including symbols, just comment the line starting with "DEBUG_FLAGS" (using # character )

@ocornut : in the diff below, I think I corrected a little issue in the Linux Makefile. Precisely, CXXFLAGS = (something) hides the previously defined flags.

diff --git a/examples/example_sdl_opengl3/Makefile b/examples/example_sdl_opengl3/Makefile
index 6987411..1786a67 100644
--- a/examples/example_sdl_opengl3/Makefile
+++ b/examples/example_sdl_opengl3/Makefile
@@ -20,7 +20,7 @@ SOURCES += ../imgui_impl_sdl.cpp ../imgui_impl_opengl3.cpp
 SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp ../../imgui_widgets.cpp
 OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
 UNAME_S := $(shell uname -s)
-
+DEBUG_FLAGS = -g
 ##---------------------------------------------------------------------
 ## OPENGL LOADER
 ##---------------------------------------------------------------------
@@ -45,8 +45,8 @@ CXXFLAGS = -I../libs/gl3w
 ifeq ($(UNAME_S), Linux) #LINUX
        ECHO_MESSAGE = "Linux"
        LIBS = -lGL -ldl `sdl2-config --libs`
-
-       CXXFLAGS = -I../ -I../../ -I../libs/gl3w `sdl2-config --cflags`
+       CXXFLAGS += ${DEBUG_FLAGS}
+       CXXFLAGS += -I../ -I../../ -I../libs/gl3w `sdl2-config --cflags`
        CXXFLAGS += -Wall -Wformat
        CFLAGS = $(CXXFLAGS)
 endif

  1. run the debugger
 gdb64 --args ./example_sdl_opengl3
  1. Drag the Hello window at the bottom of the main window (just put it at the border, no need to overlap)
  2. click on clear color.

Expected : should open the colorpicker

  1. Once the colorpicker is open, move its window to overlap the main window.

  2. Then, move the mouse cursor inside the colorpicker window, exactly over "Original" color rectangle.
    Once over this area, another rectangle box opens (probably a tooltip ?)
    If the tooltip rectangle overlaps the main window, the crash occurs.
    (oppositely : it the tooltip rectangle appears inside the main window, no crash).

This crash is 100% reproductible, and I think some new windows are uninitialized, or lost their position, but I can be wrong.

Last but not least : english is not my native language, so feel free to correct me. TIA :-)

@ebachard You confirmed what I noticed.

I do not understand well the code but all I what I could traced is PlatformUserData is set to NULL in ImGui_ImplGlfw_DestroyWindow then used by ImGui_ImplGlfw_GetWindowPos and not dropped by UpdateViewports inside the for (int n = 0; n < g.Viewports.Size; n++) and the segfault occurs when accessing to the NULL pointer. This is what you can read in my looooong logs :)

For me is not a platform specific issue because the code is the same for all archi. I think it's most an algorithm issue or race condition between the 2 threads. But I do not understand the whole code so I cannot help more. Anyway I'm not sure this is related with flickering effects.

Did you try with valgrind ? It detects a memory corruption before the segfault occurs (which comes randomly but several cycles after). You can use rr (record & replay) which record the execution and call gdb (unfortunately I cannot use it with my Ryzen CPU).

If this can help: to trace stack, I use backward. Here the Makefile to change (also working for Darwin, never tested on Windows):

	SOURCES = backward.cpp main.cpp

	LIBS = -lGL `pkg-config --static --libs glfw3` -ldw
	CXXFLAGS += -I../ -I../../  `pkg-config --cflags glfw3` -DBACKWARD_HAS_DW=1
	CXXFLAGS += -Wall -Wformat -O2 -g -fomit-frame-pointer
	CFLAGS = $(CXXFLAGS)

You have to add in Makefile the file backward.cpp the library -ldw the define -DBACKWARD_HAS_DW=1 gcc options -O2 -g -fomit-frame-pointer and maybe to do apt-get install libdw-dev

I've truncated the bug report (after the crash) but there the stack calls (which rephrases what we wrote):

ImGui::NewFrame();
UpdateViewports();
viewport->Pos = g.PlatformIO.Platform_GetWindowPos(viewport);
glfwGetWindowPos(data->Window, &x, &y);

The following message is to report the macOS compatibility of the viewport branch using the example_glfw_opengl3binary.

  • OS: macOS 10.12.6
  • Hardware: MBA Late 2013
  • ImGui version: 1.66 WIP (056af2b)
  • GLFW version: 3.2.1 and 3.3.0

  • Crash encountered: none

  • Issue encountered:

    1. The created child viewport gains the focus and it is no more possible to move it outside of the main viewport. It is necessary to release the LMB, press it again on the child viewport to move it completely outside of the main viewport.
      imgui-viewport-example-glfw-opengl3-reduced

    2. When resizing a child viewport (from the bottom-right corner or the top and bottom edges), this one jumps (possible rounding error?). Note: in the following GIF, the child viewport has no problem to move outside of the main viewport because the fix proposed in the next section was applied.
      imgui-viewport-example-glfw-opengl3 nofocus_on_show-resize-glitch-reduced

  • Possible fix

    1. No way was found with GLFW 3.2.1. However, GLFW 3.3 introduced a new window attribute that fixes this problem: GLFW_FOCUS_ON_SHOW. I tested it (see the commit Alzathar@d560773 for the modifications in example_glfw_opengl3) and the child viewport can move without problem. This code was also tested without problem under Windows 10. Unfortunately, this may introduce another problem. Indeed, as explained in the commit, the previous viewport keep the focus. Supplementary code is needed to give to the child viewport the focus when the user stops to move it and release the LMB. Is it a problem or not?
      imgui-viewport-example-glfw-opengl3 nofocus_on_show-reduced

@Alzathar : can you please confirm the crash we decribed with @Lecrapouille (the clear color one) doesn't occur on Mac OS X ?

TIA

@ebachard On macOS, I have not the segfault reported in this comment #1542 (comment)

imgui-viewport-example-glfw-openg_macos_hello-color

I tried with other configurations (hello world window in a child viewport, color picker in another child viewport when appearing, main viewport without window), and there is no segfault. However, I found one minor issue when a window is in a child viewport and is collapsed and then expanded. When expanded, the window moves to the top of the screen, expand, and then moves to the previous position. Note: in the following GIF, the expanded window seems to move to the top only the first time it is collapsed and expanded, but that is not the case. This is a problem with the screen recording at 15FPS. Each time you collapse and expand a window, this one moves to the top.

imgui-viewport-example-glfw-openg_macos_hello-color-outside

I do not have OSX now, can you try moving your mouse like on this video (sorry my video is not nice : the "clear color" window is not appearing because of the gif recorder grabbing the focus):
crash

@Alzathar : sorry, my explanation was probably unclear. I'll try using other words:

The main point is: open an openGL child window outside of the main window (a glfwWindow for you, if I'm not wrong). To respect this test case, you'll have to put the Hello window near to the inside border of the glfw Window. Then, move the cursor over the "Original" visual, in order to make the tooltip rectangle appear with one part inside and one part outside of the main glfw Windows (in your last gif, the hello window is already outside the main glfw Window, and this is another test case).

The example we propose uses the clear color, based on the Hello window, but I'll try to find another example, to try to isolate the reason (the "WHY" ). The "WHAT" being the crash, caused by null coordinates.

@Lecrapouille: I think your idea is interesting, and maybe the flickering could be caused by some rounding issue (or something similar). But I need to find the time to debug (not before next friday, sorry). Last but not least, thank yu very much for the valgrind tips. I'm used to gdb, but I'll git valgrind a try, of course.

@Lecrapouille I tried like in your video (switching quickly between the hello window and the clear color window) and I have no segfault. @ebachard I also reproduced the steps detailed in #2117 (comment), but there is no segfault either.

I think we can say this crash is only related to Linux. Based on what I read in this discussion, there are different versions of Linux, different GPUs (Ryzen, Intel), different WMs (compositing or tiling), different backends (GLFW, SDL2) and maybe different versions of the viewport branch of Dear ImGui. If I read correctly, the crash happens in all configuration with compositing WM. However, it is not confirmed with the i3 tiling manager (@s-ol did you have a crash for the sdl_opengl3 example under i3?). It is not yet clear for me if the problem is related to the WM or Dear ImGui. Because compositing WM does supplementary processing when a window is created and destroyed, the problem might be related to the speed of the WM to process the request sent by Dear ImGui to create a window. An idea would be to assert the result of the glfwCreateWindow function in the example_gflw_opengl3 (line 388). You could add the line assert(data->Window) to verify if the window is correctly created.

You should try this.

glfwCreateWindow is not the cause. I added assert(data->Window) and this does not crash. I persist to say the only cause is made by this line where NULL pointer is used. Finding why it's still used will fix your issue. If you want a quick & dirty workaround add && viewport->PlatformUserData != NULL in the if of this line this fix the segfault but not the flickering effect.

I tried with example_sdl_opengl3 for Linux (I did not before) I have no issue (not flickering, no segfault, no NULL pointer in my trace). The only drawback I noticed is that I loose the mouse focus on firefox, Linux console ... I cannot use the keyboard (like entering this issue for example).
crash2

I tried to diff code source SDL vs GLFW. I noticed a minor error:
SDL: bool err = gladLoadGL() == 0; vs GLFW: bool err = gladLoadGL() != 0; in main.cpp
and SDL have a little more checks against NULL (for example data->Window && missing in ImGui_ImplGlfw_DestroyWindow)

@Alzathar : sorry, I was afk all the week, but I found some time to check back at home. Indeed, you are right : the crash on Linux is very probably caused by the compositing. Once it (the compositing) is disabled, the crash previously mentionned does no longer occur.

Other test without window compositing on Linux (i.e. it is disabled): After some tries, remains one last issue : when I move an ImGui window outside of the main SDL_Window (or GLFW window depending on your choice), the ImGui window is stuck on the border, and cannot go out (and partially disappear).

Can someone confirm there is something similar ?

@Alzathar : I cannot help you: I have not this effect either on SFWL or SDL opengl3 + Debian 64bits (libSDL2-2.0.so.0.8.0, libglfw.so.3.2). I think people have different versions of these libs that may explain these different behaviors.

I just noticed a new glitch with Imgui imgui SDL + XFCE that I cannot record in gif.

When the panel color is outside, I see blinking effect on buttons of the XFCE docker. Buttons which correspond to imgui windows and their child. The blinking can be explained by:

  • the main window is releasing the docker button, then the child window is taking it
  • then the contrary: child releasing ...
    This is due to the frequency where they are painted.

Therefore once a child is outside its main window, you cannot longer use your mouse for inserting texts in other XFCE applications (firefox, console, emacs ...) its like the child windows is placed on the top of all XFCE applications which lost their mouse focus and you no longer can type on them. See my previous gif screenshot about it (upper in this post).

Finally, when changing of virtual desktop, child windows are following the new desktop and displayed on the new one (while the main window is still present on the previous desktop). With the same effect (docker blinking + no mouse focus).

For first thing: great job... and the multiple viewports is very very amazing!

I tested ImGui 565af90 in my application that use GLFW and OpenGL

On Linux and Window the program use AZDO (Approaching Zero Driver Overhead), functions available from OpenGL 4.5
In Mac OS X, for limitation of the OS, I have used the OpenGL 4.1 functionalities
I did only tests to 64 bits for OSs and application.

I tested it on Linux (Fedora 28 and Ubuntu 18.04.1 LTS), OS X 10.14 (Mojave), Windows 10, and also WINE 3.14 under Linux
The analysis of the results is shown below.
I add links to the movies of the screen captures (each few seconds): is easier to understand what I'm talking about.
I'm sorry for the animated gif, but I have captured large portions of the screen.

OS: Fedora 28
GPU: Intel HD 530
WM: Metacity
(no effect, no compiz)

https://youtu.be/ghIv3xocev0

About the ColorEdit box problem, I noticed that when shows the coloredit popup, appear a new "Untitled Window" on task bar.
(The ImGuiConfigFlags_ViewportsNoTaskBarIcon flag: on linux do not works.)
After begin a rebound of the popup window between the main viewport (top left corner) and the correct position on desktop (near to color edit box) and continue until I move the mouse...and when the mouse left the box, few istants and the application crashes.

OS: Fedora 28
GPU: Intel HD 530
WM: Metacity
(no effect, no compiz)

https://youtu.be/HLCyDMQmzYU

The ImGuiConfigFlags_ViewportsNoTaskBarIcon flag: on linux do not works
Same thing with a simple text popup (like helper (?) function of imgui_demo): "Untitled window" on task bar, but no rebounds on main Viewport (perhaps because there is not a texture like in coloredit?)
when i move away the mouse the application crashes, same as for the ColorEdit

OS: Fedora 28
GPU: Intel HD 530
WM: Metacity
(no effect, no compiz)

https://youtu.be/yZVxy6MEE_I

There is a problem also when I resize a window near edge of screen (Desktop): when i reach the border, the window increases on the opposite side:

OS: Ubuntu 18.04.1 LTS
GPU: AMD RX 480
WM: Metacity
(no effect, no compiz)

https://youtu.be/fin6E3pIjJA

Strange rebound between main viewport and desktop when I reach the border of screen (desktop) with the window (also in Fedora).
And also here, as in fedora, when it comes out of the main viewport: the main window (with main viewport) lose the focus, and the mouse lose the drag from the new created window: here GLFW_FOCUS_ON_SHOW do not works.

OS: Wine 3.14 under Fedora 28
GPU: Intel HD 530
WM: Wine 3.14 under Metacity
(no effect, no compiz)

https://youtu.be/4imddy_QeTI

I tested Win64 executables on wine 3.14, under Fedora 28, with OpenGL 4.5.
Here on linux, where crashes often, with wine run very fluid: no crash and no big problems (In wine, like in Windows, ImGuiConfigFlags_ViewportsNoTaskBarIcon works, obviously) .
It Works like in Windows 10: same behaviour. (look below, last test)

OS: OS X 10.14 (Mojave)
GPU: AMD RX 480

https://youtu.be/jKg9yjDiZUk

The app is functional: no crash.
Minor troubles:
Same issue on resize as marked from Alzathar and others.
GLFW_FOCUS_ON_SHOW works well on move the window from main viewport to outside, but outside, the inactive window, need TWO click to get focus: with the first it come topmost, with second get the focus.
Here, on the taskbar, you only see the main program icon with or without ImGuiConfigFlags_ViewportsNoTaskBarIcon.

OS: Windows 10.
GPU: NVidia RTX 2070

https://youtu.be/boL63aLjANk

The app is almost perfect: I used it for a long time an works fine, no crashes, no errors!
Only thing I noticed, when I step on the ColorEdit box (in a window outside main viewport) with the mouse, the popup appear for an istant on main viewport (top left corner), like in linux, but only once, for very few frames,

vlcsnap-2018-11-07-08h11m18s596

and after it is positioned in the correct position.

vlcsnap-2018-11-07-08h11m47s540

It does it again if I move the mouse and reposition it.
On RTX 2070 is very rapid, the movie capture do not catch it all times

That's all.
If I need more tests, particular outputs, or anything else, I will be happy to be useful.

Michele

Thank @BrutPitt for your reports and all the details. It will take me a while to get through all the stuff in this thread and I'll probably need to obtain Mac/Linux machines to make more sensible possible on many of those machines.

This weekend, with some time available, I did some tests/debug on linux.
If it could be useful: the application crash on the ColorEdit box popup window, in the ImGui_ImplGlfw_GetWindowPos(ImGuiViewport* viewport) function of imgui_impl_glfw.cpp file (line:504), when call glfwGetWindowPos(data->Window, &x, &y);

static ImVec2 ImGui_ImplGlfw_GetWindowPos(ImGuiViewport* viewport)
{
    ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
    int x = 0, y = 0;
    glfwGetWindowPos(data->Window, &x, &y);
    return ImVec2((float)x, (float)y);
}

because data == NULL

Calls stak

ImGui_ImplGlfw_GetWindowPos imgui_impl_glfw.cpp:504
ImGui::UpdateViewports imgui.cpp:7303
ImGui::NewFrame imgui.cpp:3307
mainImGuiDlgClass::renderImGui uiMainDlg.cpp:1945
mainGLApp::mainLoop glApp.cpp:502
main glApp.cpp:540
__libc_start_main 0x00007ff29e79e11b
_start 0x00000000004086da

(This happens occasionally, almost infrequently, not in every call)

If I use:

if(data && data->Window) glfwGetWindowPos(data->Window, &x, &y);

the application does not crash anymore, nor with the ColorEdit popup, nor with any other popup.
But I guess that we must understand why data==NULL.

Little update:

Using up-to-date viewport branch
Processor : Intel x86_64
Linuxmint 18.3
using SDL2 + OpenGL3
WM : Gnome + Compiz compositor

I just wanted to add, that there is no more crash with recent changes. Thanks @ocornut !

Remain the window dancing when moving close to the limit of the main window. After some tries, it appears that:

  • moving the window very slowly close to the border of the main window does not cause the issue
  • moving horizontaly causes horizontal danse issue only
  • same issue : moving the ImGui window out of the main SDL window verticaly causes a vertical dance only when close to the border.

Once out of the main window : no problem.

Last but not least : same issue with other window manager ( e.g. metacity without compositor)

@ocornut : I think you are very close to something working well.

Everyone on SDL, can you try replacing the code that sets the io.MousePos to use the absolute mouse coordinates without a back and forth:

e.g in imgui_impl_sdl.cpp

    SDL_Window* focused_window = SDL_GetKeyboardFocus();
    if (focused_window)
    {
        // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
        // The creation of new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
        int wx, wy;
        SDL_GetWindowPosition(focused_window, &wx, &wy);
        SDL_GetGlobalMouseState(&mx, &my);
        mx -= wx;
        my -= wy;
    }
    if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)focused_window))
        io.MousePos = ImVec2(viewport->Pos.x + (float)mx, viewport->Pos.y + (float)my);

Change to

    SDL_Window* focused_window = SDL_GetKeyboardFocus();
    if (focused_window)
    {
        // SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
        // The creation of new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
        SDL_GetGlobalMouseState(&mx, &my);
    }
    if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)focused_window))
        io.MousePos = ImVec2((float)mx, (float)my);

And for GLFW in imgui_impl_glfw.cpp you may try to change

double mouse_x, mouse_y;
glfwGetCursorPos(window, &mouse_x, &mouse_y);
io.MousePos = ImVec2((float)mouse_x + viewport->Pos.x, (float)mouse_y + viewport->Pos.y);

to

double mouse_x, mouse_y;
int window_x, window_y;
glfwGetCursorPos(window, &mouse_x, &mouse_y);
glfwGetWindowPos(window, &window_x, &window_y);
io.MousePos = ImVec2((float)mouse_x + (float)window_x, (float)mouse_y + (float)window_y);

As fast feedback:

I'm using up-to-date viewport branch
Processor : Intel x86_64
Linuxmint 18.3
using SDL2 + OpenGL 3.0 + glsl 130 (works the same way using OpenGL 3.3 and glsl 150, manualy modified)

After applying your changes + make clean && make, I got one little warning:

./imgui_impl_sdl.cpp:287:24: warning: unused variable ‘viewport’ [-Wunused-variable]

That's imho nothing important, and after that, I tested the sdlgl3_example with the following Window Managers :

  • gnome + Compiz compositor
  • gnome + Metacity with and without compositor
  • gnome + Marco with software compositor, and no compositor

=> I didn't detect any issue.

👍 congratulations !!

Is there anything else to test ?

I forgot : reversing the changes, the flicker is back, so imho you solved this issue.

Nice :)

Is there anything else to test ?

Could you test the GLFW version? Also hoping for feedback from other users.

This code made sense to allow the same code to work with both Viewport enabled and disabled, but instead I will add an if/else block.

Nice :)

Is there anything else to test ?

Could you test the GLFW version? Also hoping for feedback from other users.

This code made sense to allow the same code to work with both Viewport enabled and disabled, but instead I will add an if/else block.

I just tried 89a530b (viewport branch) on my Retina screen (macOS 10.14.1/GLFW 3.2.1/OpenGL 3). The clipping bug that I reported earlier is still there (with and without the code change that you suggested).

The docking branch on the other hand works great and is already integrated in my current project.

As suggested, I did a kick test using glfw:

Same conditions:

  • using up-to-date viewport branch
  • Processor : Intel x86_64
  • Linuxmint 18.3
  • using glfw 3.2 + OpenGL 3.0

After applying your changes + make clean && make, I still see two issues:

  1. moving an ImGui window outside of the glfw window:
    Starting point: glfw example + OpenGL3, both hello world and demo window inside the glfw Window.

When I try to move a Dear ImGui window outside of the glfw Window, I have to do it in two moves, because there is sort of ' resistance ' when the ImGui window border reaches and starts to overlap the glfw window border. This makes the mouse cursor no longer dragging the window, and I need to click a second time on the ImGui window to continue dragging it outside. the border. Once done, no other apparent problem occurs (e.g. no more flickering)

  1. moving an ImGui window from outside, into the glfw window :

Starting point : in the previous try, one ImGui windows was left outside of the glfw Window.

Restarting the glfw example, there is one ImGui window (here the Hello world window) outside of the glfw Window, while the demo is inside.

The issue : I simply can't drag the outside ImGui window, who's stuck to the background. Looks like it cannot be focused anymore.

No problem with the Demo window, who can be focused when put outside, and put back inside after.

Both issues described above occur with or without compositor, using:

  • Marco (without compositor, or with software compositor,
  • Metacity (without, software compositor, accelerated compositor)
  • Compiz (with compositor + hardware acceleration)

Waiting for other to confirm.

Nice progress :) on amd64 + XFCE + glfw3 I no longer notice bugs that I reported:

  • segfault when shaking the clear button panel
  • the keyboard focus on other applications (like firefox, gedit) when a window is outside the main win
  • XFCE docker buttons flickering effects.

Bug still present:

  • the outside window is still flickering
  • moving the outside window on a new virtual desktop (XFCE) and moving it makes it jumped back to the virtual desktop of the main window.

The SDL version always worked fine for me :)

@ocornut The following GIF uses the proposed patch for GLFW applied to the viewport branch commit 3a678d4 under macOS 10.12.6 (Xcode 9.2)

imgui-viewport-example-glfw-opengl3 3a678d4_optimized

Compared to the original bug report (see ii. in this comment), the jumping window problem is gone: 👍. However, you can see other issues:

  • resizing from the bottom moves the top edge
  • the window shakes when you resize from the top
  • the window jumps when you resize the window from the bottom and then the left.
  • OS: Fedora 28
  • GPU: Nvidia 1050Ti
  • WM: Mate / Metacity
  • GLFW 3.3 / OpenGL 4.5

I tested last version of viewports and apply the GLFW patch:

  • No more crash on popup window, nor on ColorEdit popup box, nor with any other popup.
  • No more "dancing" window!!! (with patch)

GREAT

On Linux remains just the little trouble of the "main window border": the window that is coming out stumbles in the edge when leaves the mainvieport, and the mouse loses the "grip" (drag).
This happens on focus changing: when the mainviewport loses the focus
EDIT: I tried glfwWindowHint(GLFW_FOCUS_ON_SHOW, false); and on Linux do not solves the problem

  • OS: OS X 10.14
  • GPU: AMD RX 480
  • GLFW 3.3 / OpenGL 4.1

Also here, as in Linux:

  • No more "dancing" window!!! (with patch)

And also on Mojave (OS X 10.14) confirm the trouble described from @Alzathar
But without the patch it's worse: the resizing (with the same problem) continues also without moving the mouse

(Posting here as ocornut told me to put it here)
Hello,

I just tried the newest docking branch(1.66b) on Linux(Ubuntu 18.10, Gnome). And noticed some serious issues. I am using the glfw_opengl3 example.

First, whenever I drag a ImGui window out of the main ImGui window, it stops dragging, probably because it lost focus. This is annoying, but might be the fault of GLFW instead of ImGUI(It works fine in the SDL example) Do you know if it's possible for me to solve this?

Second issue, when resizing the actual window in ImGUi on an external window, ImGui is resizing too slow. But when the window is resized using decorations, it works just fine:
resizingimgui
First, resizing on a normal window is shown, then resizing using ImGui handle on a decorated window, and then using native Gnome Window handle to resize. Notice how resizing with the nativie Gnome handle doesn't cause artifacts.
So, why does that happen? How is resizing in ImGui different from resizing from code? What is being done differently?(Are you maybe precalculating what the Window size should be or something?) This isn't really a bug though, it's more of an annoyance.

Could anyone help me with this?

Thanks!

Edit:
With a new commit, the shaky dragging is now resolved! Which was one of my most important problems. The resizing annoyance/artifact still remains, but is something I can live with or maybe fix myself. The part where it stops dragging also remains, but that is also something I can live with and quite likely fix myself.
Thank you very much to @ocornut for creating such a great library!

Glad this getting better with the new changes!
I now made a commit with the change I mentioned above: f3a0b17

For the rest I'm afraid I may not be able to spend much time on it, I don't even have a Linux box and I don't have a client asking for it. Some changes may requires designing and pushing patches for GLFW (see Wiki "Help Wanted"). Someone probably needs to step in and spend the required hours/days to understand and fix those things but it's not going to be a five minute thing (I spent hundreds of hours on it for Win32 and the current api). I can assist and answer some questions but I don't have the bandwidth nor energy to do for a system I am not using at the moment.

Glad this getting better with the new changes!
I now made a commit with the change I mentioned above: f3a0b17

For the rest I'm afraid I may not be able to spend much time on it, I don't even have a Linux box and I don't have a client asking for it. Some changes may requires designing and pushing patches for GLFW (see Wiki "Help Wanted"). Someone probably needs to step in and spend the required hours/days to understand and fix those things but it's not going to be a five minute thing (I spent hundreds of hours on it for Win32 and the current api). I can assist and answer some questions but I don't have the bandwidth nor energy to do for a system I am not using at the moment.

I might be able to help a bit, I am quite familliar with OpenGL and Linux, and I know how to use GLFW.
For the window out of main window dragging problem, a possible solution might be to remember you kept the mouse pressed, and just reuse that event, then wait for the mouse to get released again. A global mouse button check function might also be possible.

Hello everyone!

Unfortunately, I found another bug:
imguidragging
What's happening is that the windows are prevented from moving off my screen, so the Windows can't move off screen, but the mouse still moves down, this causes this weird thing where the dock icons move up on the window. My guess on what's going on is is that ImGui draws the buttons on the other windows as well so they are visible when dragging a window over it, but it doesn't expect the mouse to move down when the Window doesn't, thus the buttons/icons move up. Which is visible in the gif.

Is there already a fix for that? My guess on a possible fix would be to allow windows to go off screen, or use the window position instead of the mouse position for moving the docking icons/buttons.

Thanks!

@ocornut
The trouble of viewport that stops on border of the screen, there is only in Linux (tested on Fedora 28), no problem on OS X.
Did not notice this yesterday (had escaped me), but is present also on previous commit, and also w/o patch.
tttt

In the animated gif, the window remains blocked on border, but the cursor goes down, and when I release the mouse, ImGui thinks that it is still on caption, indeed, when I continue to go down, the widgets above cursor are highlighted... and the synchronization between coordinate of viewport and cursor, is lost.
Same thing on left and right border.

I'm not sure I understand exactly what you're asking, what do you want me to check: i can debug it only this evening (and I do it gladly), but for now I run windows metrics, an I notice that view port and clipping rectangles are correctly reported... also the graphics representation of viewports inside windowmetrics is correct (the window continues to go down), but on screen it appears blocked on the edge.
Edit: Also windows position, from windows metrics, appears to be reported correctly... it continues to increment while it is blocked
but I'll be able to study in deep only later

An animated gif of what I said / tested
tttt1

I am assuming the position limitation is enforced by your window manager?

When we call:

        // Apply Position and Size (from ImGui to Platform/Renderer back-ends)
        if ((viewport->LastPlatformPos.x != viewport->Pos.x || viewport->LastPlatformPos.y != viewport->Pos.y) && !viewport->PlatformRequestMove)
            g.PlatformIO.Platform_SetWindowPos(viewport, viewport->Pos);

Can you

  1. call g.PlatformIO.Platform_GetWindowPos() right after to see if the reported position differs already? (aka the window manager modified the position we requested).
  2. add printf log to the code doing viewport->PlatformRequestMove = true and see if the modification is ever reported by the SDL/GLFW event system.

I'm hoping that at least 1) is true, in which case you may need to always call Platform_GetWindowPos() after calling Platform_SetWindowPos(), if they differ we will need to convey that information by setting PlatformRequestMove=true in UpdatePlatformWindows() and making sure this is not immediately clearerd at the end of the function.

Now I have little time, but I did, on the fly:

Window position before to move:

GetWndPos   - x: 1403, y: 883
ViewportPos - x: 1403, y: 883
GetWndPos   - x: 1403, y: 883
ViewportPos - x: 1403, y: 883

When I starting to move, i get already some difference:

GetWndPos   - x: 1403, y: 891
ViewportPos - x: 1403, y: 893
GetWndPos   - x: 1403, y: 891
ViewportPos - x: 1403, y: 893
GetWndPos   - x: 1403, y: 891
ViewportPos - x: 1403, y: 893
GetWndPos   - x: 1403, y: 891
ViewportPos - x: 1403, y: 895
GetWndPos   - x: 1403, y: 891
ViewportPos - x: 1403, y: 896
GetWndPos   - x: 1403, y: 895
ViewportPos - x: 1403, y: 898
GetWndPos   - x: 1403, y: 898
ViewportPos - x: 1403, y: 899
GetWndPos   - x: 1403, y: 898
ViewportPos - x: 1402, y: 901

But I guess it can be normal

When I reach the edge (975 upper y of window):

ViewportPos - x: 1395, y: 975
GetWndPos   - x: 1396, y: 971
ViewportPos - x: 1395, y: 977
GetWndPos   - x: 1395, y: 975
ViewportPos - x: 1395, y: 979
GetWndPos   - x: 1395, y: 975
ViewportPos - x: 1395, y: 981
GetWndPos   - x: 1395, y: 975
ViewportPos - x: 1394, y: 984
GetWndPos   - x: 1394, y: 975
ViewportPos - x: 1394, y: 985
GetWndPos   - x: 1394, y: 975
ViewportPos - x: 1394, y: 988
GetWndPos   - x: 1394, y: 975
ViewportPos - x: 1394, y: 991
GetWndPos   - x: 1394, y: 975
ViewportPos - x: 1393, y: 994
GetWndPos   - x: 1393, y: 975
ViewportPos - x: 1393, y: 996
GetWndPos   - x: 1393, y: 975
ViewportPos - x: 1393, y: 999
GetWndPos   - x: 1393, y: 975
ViewportPos - x: 1393, y: 1000
GetWndPos   - x: 1393, y: 975
ViewportPos - x: 1392, y: 1003
GetWndPos   - x: 1393, y: 975
ViewportPos - x: 1392, y: 1007
GetWndPos   - x: 1392, y: 975
ViewportPos - x: 1392, y: 1008
GetWndPos   - x: 1392, y: 975
ViewportPos - x: 1392, y: 1009
GetWndPos   - x: 1392, y: 975

This evening more depth test

  • Fedora 28
  • WM: Mate / Metacity
  • GPU NVidia 1050Ti:

I think it's a problem of glfwSetWindowPos on LINUX

  • I tried to call it after g.PlatformIO.Platform_GetWindowPos(viewport) with same result.
  • I tried with my main window, to let go it out of the edge, but it no go out: It repositions itself always in line with the edge

I test it a little bit..
EDIT: My GLFW version is 3.3 (end October/November)... but now I try different versions
Has someone else problems with GLFW and windows that do not go out of the desktop?
What version of GLFW?

EDIT more: With same version of GLFW, on Windows 10 and on OS X 10.14.1, the windows can go (partially) out the desktop with glfwSetWindowPos call

OS: Fedora 28
WM: Metacity and Marco with MATE Desktop Environment
GPU NVidia 1050Ti

OS: Ubuntu 18.04 LTS
WM: metacity, xfwm4 and marco with MATE and XFCE Desktop Environment
GPU RX 480

GLFW 3.3.0 and 3.2.1
OpenGL 4.1 and 4.5

I'm Sorry for another post, but I found the cause of the problem.
On linux, in some Windows Managers (metacity/marco/xfwm4) there is a feature called placement mode "snapping window": a window in contact with a border of other window, or in contact with border of desktop, causes a slight "resistance" of the mouse before "unsticking" the window and moving again , and this blocks 'glfwSetWindowPos' on edge of desktop.
(snapping has confused me)

Indeed, if I help the window get over the edge, glfwSetWindowPos works again:
tttt2
In the animated gif, glfwSetWindowPos is called inside main loop, and the window should be positioned always over the lower edge, but it fails.
If I drag it over the border and leave it, the window goes to the right place.
(note the drag resistance of the mouse on the edge)

I did not find the way to disable this feature (at least for now) from within the above-mentioned windows managers, there is only may to change the placement type, via dconf-editor. I tested glfwSetWindowPos and ImGui-viewports under Compiz (with Place Window option disabled) and this problem does not occur.

EDIT: with snapping enabled, also Compiz manifest same trouble: the problem is really the snapping feature
The option that on Compiz enable/disable the "desktop constraint" of the window, is Place Window (not snapping)

I suspect this is because the window type hints may be incorrect on the floating window.
_NET_WM_WINDOW_TYPE_TOOLBAR is probably the ATOM that should be used.

I expect this is what the window manager is using to decide whether to apply the snappy feature. It's at least worth a check. If the window has the_NET_WM_WINDOW_TYPE_NORMAL ATOM it will probably always snap...

Tank you for your suggestion, but it does not seem to work:

    Atom type = XInternAtom(_glfw.x11.display,"_NET_WM_WINDOW_TYPE", False);
    Atom value = XInternAtom(_glfw.x11.display,"_NET_WM_WINDOW_TYPE_TOOLBAR", False);
// tried also _NET_WM_WINDOW_TYPE_UTILITY
    XChangeProperty(_glfw.x11.display, window->x11.handle, type, XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);

I fear it may be a little more complex. I read that is need to play with override redirect attribute of the window, but after window manager will stop doing anything for us.

Anyway, perhaps it's more a GLFW "problem", if it is really a problem, because the same behavior there is also in SDL.

This sounds definitely like an X11 problem. There are a ton of windows hint possibilities and every WM deals with it differently. MATE does honor EWMH. So I'm pretty sure this is the issue. Dealing with X11 Atoms is like pulling teeth. Here is the spec:

https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130317606816

Sorry I can't be more help...

PS. There may be an exclude option on MATE to only affect certain window types. I'm not very familiar with MATE so I can't say.

For the record, I have tested the most recent Multi viewports branch on Linux with my own software, and it works very well.

Using : LinuxMint (custom kernel 4.15.18, Mate + Compiz + hardware compositing), using g++-7 and gcc-7

miniDart 0.9.2 + SDL2 (2.0.9) + OpenGL 3 ( glslversion #130) + up to date viewports branch.

The issues I found are for most of them on my side (my fault). Here are the remaining one I found on Linux, if ever they are valid (maybe my fault too):

  • First issue : was not easy to implement MainMenuBar , but I finally found a solution (hack ?).

The code I'm using (maybe I did something wrong ?)

// kept to illustrate the example
static bool open = true;
ImGuiWindowFlags mD_window_flags = 0;

// for testing purpose : will be simplified soon
static bool no_titlebar = true;
static bool no_resize = true;
static bool no_move = false;
static bool no_scrollbar = false;
static bool no_collapse = true;
static bool menu = false;

if (no_titlebar)  mD_window_flags |= ImGuiWindowFlags_NoTitleBar;
if (no_resize)    mD_window_flags |= ImGuiWindowFlags_NoResize;
if (no_move)      mD_window_flags |= ImGuiWindowFlags_NoMove;
if (no_scrollbar) mD_window_flags |= ImGuiWindowFlags_NoScrollbar;
if (no_collapse)  mD_window_flags |= ImGuiWindowFlags_NoCollapse;
if (menu)         mD_window_flags |= ImGuiWindowFlags_MenuBar;

// some geometry. 24.0f seems to be the height of the main menubar
ImVec2 windowSize(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y - 24.0f);
ImGui::SetNextWindowSize(windowSize);

// Without the two lines below, we can obtain 2 windows :
// -  one sort of ghost window (no move, no borders ..., located under the main one,
// -  one main window receiving no events ...

ImVec2 main_viewport_pos = ImGui::GetMainViewport()->Pos;
// after we reduced the window size, we translate it from the same value
// Last : check whether the position is really 0,24 for this window in imgui.ini
ImGui::SetNextWindowPos(ImVec2(main_viewport_pos.x,main_viewport_pos.y + 24.0f));

if (ImGui::Begin(APPLICATION_VERSION_STRING, &open, mD_window_flags))
{
    if (ImGui::BeginMainMenuBar
    {
         if (ImGui::BeginMenu(ICON_FA_FOLDER_OPEN_O FILE_OPEN_MENU_ENTRY))
            {
                ShowMenuFile();
                ImGui::EndMenu();
            }
       ....
  • Second issue : context not rendered when a new viewport is created (please fix my wording if I'm not precise). as example, I have added the recursive menu. Inside the main window, I'm rendering an ImGui::Image(). The instructions to reproduce the issue (fully reproducible) is described below. In short, when then the popup menu goes outside of the main window, the content is no longer drawn.

Image 1 : before menu population
multi_viewports_rendering_issue_before
Image2 : after

multi_viewports_rendering_issue_after

Workaround: resize the window, and everything is ok.

Second way to reproduce : move a window outside, and resize it while overlapping the main window => same result : the image in the main window is no longer rendered (same context seems to be cleaned up). Same workaround : resize the window.

Last, I didn't find the time to try on Windows (same code, after cross compilation using mingw)

Feel free to ask if I forgot something.

Quick update : tested today (2019 january 3rd 12h00 french hour), with a fresh git pull, and no change: the same issues occur, the both ways.

Is there some list of things to test / fix on Linux? Minimal repro cases will be very appreciated, so I can focus on lower level details.

Is there some list of things to test / fix on Linux? Minimal repro cases will be very appreciated, so I can focus on lower level details.

There are enough bugs reported, what we need isn't just testing, we need work toward fixes.

Another thing is there are 3 dangling GLFW issues listed at the bottom of this page:
https://github.com/ocornut/imgui/wiki/Help-Wanted

If anyone can contribute toward getting them implemented and merged in GLFW it would largely move us forward. Even just commenting on the issue would constitute a de-facto manifestation of interest which may sway maintainers (don't abuse of that), but mostly GLFW needs help in the form of PR covering the platforms. If you can e.g. contribute to the design discussion or provide the patch even for one platform maybe it'll move things forward.

Linux or Mac users, here are some suggestions of things you could do:

(1)
In imgui_impl_glfw.cpp we need a non-portable workaround to avoid taking focus on glfwShowWindow():

https://github.com/ocornut/imgui/blob/docking/examples/imgui_impl_glfw.cpp#L516

#ifdef _WIN32
    // GLFW hack: GLFW 3.2 has a bug where glfwShowWindow() also activates/focus the window.
    // The fix was pushed to GLFW repository on 2018/01/09 and should be included in GLFW 3.3 via a GLFW_FOCUS_ON_SHOW window attribute.
    // See https://github.com/glfw/glfw/issues/1189
    // FIXME-VIEWPORT: Implement same work-around for Linux/OSX in the meanwhile.
    if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)
    {
        ::ShowWindow(hwnd, SW_SHOWNA);
        return;
    }
#endif
    glfwShowWindow(data->Window);

PR for Linux/Mac doing the equivalent workaround would be helpful.
This may be an easy changes, assuming the required includes to access the native functions are not problematic (not breaking compilation on some system). GLFW3/glfw3native.h seems to be able to handle the include for us there.
This would fix the issue where dragging/extracting a viewport loses mouse inputs on Mac/X11.

(2)
In imgui_impl_glfw.cpp, we need non-portable Linux/Mac workaround to allow marking windows as "ignoring-mouse-inputs" and having GLFW_HOVERED ignore them likewise.
This is done for Windows here:
https://github.com/ocornut/imgui/blob/docking/examples/imgui_impl_glfw.cpp#L475
This issue has suggestion of the native functions to call:
glfw/glfw#1236
This is probably a possibly a little harder to implement on imgui_impl_glfw.cpp side.
This would solve issues like #2360.

EDIT
(3)
Figure out a way to pass native hint to the WM so avoid WM positioning popup windows AND/OR rework the imgui code to more gracefully handle when a window didn't appear in the spot we expected.

EDIT
(4)
imgui_impl_sdl.cpp probably also needs similar stuff.. to be looked at.

The focus loss issue when dragging a window outside of the main viewport should be fixed with the GLFW 3.3 changes + commit #2547 (now merged).
Thanks @dougbinks, @Alzathar!

This is the point (1) highlighted above. I would still take a PR for fixing this pre GLFW 3.3 if possible (especially as the workaround is likely to still be useful with SDL)

For (1) workaround on macOS I used this:

auto cw = glfwGetCocoaWindow(window);
showCocoaWindow(cw);
#import <Cocoa/Cocoa.h>

extern "C" {
void showCocoaWindow(id window) {
    @autoreleasepool {
        [window orderFront:nil];
    }
}
}

I also experience the same issue that @BrutPitt has, but on macOS when the window snaps to the top menu bar, with this exact behavior:

https://user-images.githubusercontent.com/16171743/49624707-d2ce8b80-f9d2-11e8-8860-404e073892cc.gif

Lazzu commented

I still experience the focus loss of a window when I drag it out from or in to the main window. I haven't had much time to figure out why yet as I only today found the new cool docking branch along this feature. I'm using Linux with Gnome 3 and GLFW example.

I did some thinking on how viewports work. Since they are still work in progress i figured i will note my thoughts here as they may be of use in designing entire thing.

@ocornut you mentioned that imgui uses a "global canvas" where all the windows (part of main viewport or owning their own native viewports) are positioned. I am thinking maybe it would be a better idea to step away from this concept as it is creating all kinds of issues.

Issues i am talking about:

Incorrect recognition of mouse position. When window in a native viewport gets positioned somewhere else than imgui expects (that is, when imgui fails to properly keep track of window position) we will see imgui recognizing mouse being present in locations where it is not.

mouse-pos

Another issue appears due imgui doing it's own compositing where it should be the place of desktop environment to do it. You can see how docking guides do not align properly when (native) window is being dragged around.

docking

I understand that this is the way it is because initially imgui rendered it's own desktop. All well and good. But i think issues like these are a clear signal that this method should be abandoned for native viewports. Wayland is another important reason for moving away from global canvas as in wayland we can request preferred initial window position, but we can not explicitly set window position or read window position.


What if each native viewport had it's own canvas with it's own mouse position tracking in canvas-local coordinates? In that case native viewport would be responsible for rendering only the window(s) that it owns. Docking guides problem would be automatically fixed as destination window would render guides, dragged window would be transparent and desktop would compose both windows into a single perfect image. We also no longer need to care about z-order because desktop environment would take care of that for us. Dragging stuff from one window on to other should still work. imgui would not be aware of mouse moving through area between two viewports - but that is fine. As soon as mouse reaches viewport window - imgui would be able to react to those mouse events and handle them as needed. As for wayland - imgui may have to force native imgui windows to have native window decorations. That is mostly fine.

So that is that. Any thoughts?

Those who have problems with the window manager conflicting with this because they reassign pop/size, could you try in UpdateViewportsNewFrame() to replace the block that starts with

// Update Position and Size (from Platform Window to ImGui) if requested.

with

// Update Position and Size (from Platform Window to ImGui) if requested.
// We do it early in the frame instead of waiting for UpdatePlatformWindows() to avoid a frame of lag when moving/resizing using OS facilities.
if (!(viewport->Flags & ImGuiViewportFlags_Minimized) && platform_funcs_available)
{
    ImVec2 platform_pos = g.PlatformIO.Platform_GetWindowPos(viewport);
    ImVec2 platform_size = g.PlatformIO.Platform_GetWindowSize(viewport);
    if (viewport->LastPlatformPos.x != platform_pos.x || viewport->LastPlatformPos.y != platform_pos.y)
        viewport->PlatformRequestMove = true;
    if (viewport->LastPlatformSize.x != platform_size.x || viewport->LastPlatformSize.y != platform_size.y)
        viewport->PlatformRequestResize = true;

    if (viewport->PlatformRequestMove)
        viewport->Pos = viewport->LastPlatformPos = platform_pos;
    if (viewport->PlatformRequestResize)
        viewport->Size = viewport->LastPlatformSize = platform_size;
}

And see if that improves the situation for you?
The idea being that platform assigned pos/size should always "win" there.
I'm curious because some of my work on Windows may be affected by same issue, but it's way more obvious with Linux WMs and if we can fix the case of Linux WMs we'd be better off.

And see if that improves the situation for you?

I tried this on macOS and it somewhat improves the situation, but adds other issues. Though, take into account that testing was on a bit older commit (we're still on the one that merged 1.73 into docking, ie 6994bf1). It did fix the issue of widgets logically being offset from visual representation, but it added the following issues:

  • Window now gets stuck if it's moved into the top menu bar. I would expect it to slide horizontally.
  • Window can't be dragged into another monitor that is above the top menu bar. You can see widgets shifting downwards and pink background appearing when window is supposed to jump into another monitor.

ezgif-3-a9605ca59614

I'm having a similar issue as @Lazzu where if I move the ImGui window outside of the main window, it loses focus and I have to click it again to continue dragging it. I'm not sure if this is the right place to post this, but I thought I'd give it a shot.
I am on Arch Linux and I am using the latest version of GLFW 3.3.2 with x11.

Please nevermind. The issue was on my side: return to mesa 19.3.0 fixed the crash, and docking + viewport seems to work well, with the last changes (including the resync with 1.76).

I deleted all the information I previously posted. Apologies for the noise.

Thanks a lot for such features, they are extremely usefull !!

Some extra reference on the topic of allowing floating windows with WM such as i3:
godotengine/godot#5265

Just sharing recent knowledge in case this wasn't covered before. On macOS Catalina, it seems that the hack for the window coordinates w/ GLFW is no longer required:

static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
{
    ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData;
-#if __APPLE__
-    // Native OS windows are positioned from the bottom-left corner on macOS, whereas on other platforms they are
-    // positioned from the upper-left corner. GLFW makes an effort to convert macOS style coordinates, however it
-    // doesn't handle it when changing size. We are manually moving the window in order for changes of size to be based
-    // on the upper-left corner.
-    int x, y, width, height;
-    glfwGetWindowPos(data->Window, &x, &y);
-    glfwGetWindowSize(data->Window, &width, &height);
-    glfwSetWindowPos(data->Window, x, y - height + size.y);
-#endif
    data->IgnoreWindowSizeEventFrame = ImGui::GetFrameCount();
    glfwSetWindowSize(data->Window, (int)size.x, (int)size.y);
}

I don't know if that's possible to do a if-check to keep this change specific to macOS versions prior to Catalina, though.

Ubuntu KDE system, example_glfw_opengl3, with GLFW updated to 3.3-stable, I'm seeing two issues:

  • Dragging a window from the primary application viewport (the "Dear ImGui GLFW+OpenGL3 example" OS window) to outside the primary application viewport maintains mouse focus (so that issue is fixed), but there's a window ordering oddity--the dynamically created viewport ends up ordered behind the main application (e.g. it "pops under"), and it stays behind it if the drag is stopped outside the main window.

  • Dragging the "Hello, world!" window from when it's docked within the "Dear ImGui Demo" viewport to outside that viewport loses mouse focus (so the drag instantly stops) in the same way it used to from the main application.

Hey there, I'm experiencing a strange issue with viewport window sizes on macOS

OS: macOS 11.0.1 (Big Sur)
Hardware: MBP Early 2015
ImGui version: 1.80 WIP (4da92b8)
Implementation: SDL 2.0.12_1 + OpenGL 3 (version GL 4.1/GLSL 410 core, also tried with GL 3.2/GLSL 150)
Crash encountered: none


Issue encountered:

  1. Behaviour around viewports when above or below the main viewport using two monitor. The monitors are arranged with one on top of the other.

  2. If the secondary viewport is on the same monitor as the main viewport, everything works as expected

  3. If the main viewport is on the monitor below the secondary viewport, the secondary viewport is rendered way bigger than the viewport size and hence clipped.

ezgif com-video-to-gif

  1. If the main viewport is on the monitor above the secondary viewport, the same behaviour as 3 occurs but in reverse, the secondary viewport is rendered way smaller than the viewport size and hence the viewport is half filled

ezgif com-optimize

  1. Rearranging the displays side by side, the same issue arises, with the right-most display acting as the bottom display.

Has anyone else been facing this issue?

Hi Pierre,

As far as I can remember, you have to check the frame buffer scale. On MacOS, the main display (laptop) has a frame buffer scale of 2.0 while your second monitor is likely to have a frame buffer scale of 1.0.

Like in the snippet below, we had to do the folllowing:

io.DisplaySize = ImVec2(FrameBufferWidth / FrameBufferScale, FrameBufferHeight / FrameBufferScale);
io.DisplayFramebufferScale = ImVec2(FrameBufferScale, FrameBufferScale);

Then in our rendering code, we take those values into account properly as well.

I'm afraid I don't have a more precise answer, but I hope this will help anyway.

Tau5 commented

I don't know if this is even related to this feauture but I have found that on these windows the cursor position has an offset of some sort

imbug

I don't know if this is even related to this feauture but I have found that on these windows the cursor position has an offset of some sort

This is a known bug, that manifests when you drag the window out of bounds, and OS is applying position constraints on the window. You're most likely dragging the window upwards, and window manager is keeping it inside the screen bounds, so actual window position and position where ImGui thinks the window is are getting out of sync. You can read other posts in the thread, and ocornut also posted a partial fix (at least I confirmed that it partially works on macOS).

First of, the Dear ImGui examples are very stable on the master branch running on Wayland with Sway. This project is really an incredible example of solid software engineering!

I went on to try the docking branch, and unfortunately, in it's current state it renders the use of Dear ImGui entirely broken when running a tiling window manager (such as Sway on Wayland).

I tried running the docking branch (rev bb26751) using a tiling window manager (Sway) on Wayland, and unfortunately it was very unstable. Running the GLFW example examples/example_glfw_opengl3 resulted in the following crash when launching.

example_glfw_opengl3 (docking)> ./example_glfw_opengl3 
Glfw Error 65544: Wayland: Focusing a window requires user interaction
Glfw Error 65544: Wayland: Window position retrieval not supported
Glfw Error 65544: Wayland: Window position retrieval not supported
Glfw Error 65544: Wayland: Window position setting not supported
Glfw Error 65544: Wayland: Window position setting not supported
xdg_wm_base@9: error 3: xdg_surface must not have a buffer at creation
Glfw Error 65544: Wayland: Window position retrieval not supported
Glfw Error 65544: Wayland: Window position retrieval not supported

The SDL example examples/example_sdl_opengl3 successfully launched, but the navigation (moving windows, docking windows, etc) was impossible to use; and the offset of the mouse cursor would often desync with the UI, such that it was e.g. off by -150 px as compared to the displayed hover effect in the UI.

I'm adding this as a data point for the compatibility of the Linux docking branch, as the experience of using Dear ImGui went from a very stable one, to an unusable one (in it's current state).

To try to convey the feeling of trying to "control" (e.g. move, dock the windows) the Dear ImGui windows of the example program of the docking branch running on a tiling window manager, I'll include a few videos below, as capturing this experience in words is difficult.

I know that what the docking branch is trying to achieve is quite incredible, and thus I expect there to be complications like these to sort out. As such, consider this a data point and user experience report from someone who is really excited about Dear ImGui development, not as a negative.

Cheers,
Robin

mouse desync:
https://user-images.githubusercontent.com/1414531/105779299-57dbdc80-5f6e-11eb-9c7a-8266540444b1.mp4

trying (and failing) to move windows
https://user-images.githubusercontent.com/1414531/105779301-590d0980-5f6e-11eb-93e5-6b90d4c934fd.mp4

trying (and failing) to dock
https://user-images.githubusercontent.com/1414531/105779306-5a3e3680-5f6e-11eb-88e6-b0de44a9ce4f.mp4

riri commented

Any chance the @rokups workaround (at least for GLFW) be applied soon, until GLFW guys fixes it?

If not perfect (I also have the offset issue, also unresponding viewports when initially detached), it is at least much more usable

emoon commented

I have been playing around a bit with this the last days and ran into a small issue on my setup. I use Ubuntu with i3.

So what happens is when I drag the window outside of the main window i3 will force resize the window (which just got created) to a new size as it becomes docked to the other desktop windows. This results in the size that was setup from dear imgui doesn't match the real size of the window anymore and as rendering doesn't get to know about the new size there will be a large part of the window that doesn't get rendering and thus has garbage / uncleared pixels.

The issue is in this code

https://github.com/ocornut/imgui/blob/docking/backends/imgui_impl_glfw.cpp#L558-L561

There is a comment about why it's there, but if I remove the check for me it works as it should (i.e the system will be notified about the new size and the correct framebuffer size will be used)

I'm not sure exactly what the fix is here, but locally I will have this check removed so I just wanted to let people know about it (also sorry if this has been posted before :)

This has been the main issue on Linux for 2 years (many reports above are variations of that) and somehow nobody went through to submit a proper fix for it yet (i am not a linux user).

There’s however a variant of this which is more puzzling, according to @rokups apparently when dragging windows partly outside of screen boundaries, the WM clamp them within boundaries but the corresponding getter functions in GLFW/SDL return the values requested in the setter functions (so without clamping). This may depend on the WM thought. @rokups could you check on Daniel’s suggestion to rework the linked code above and see if we can rely on the callback values instead of the explicit getter call?

If your fix works for you this is good news. How does the interaction feels? At which points does the mouse stops mapping to window position and can you extract it back properly?

emoon commented

So in my case I plan to use floating windows only so placing a child window on top of the main window will not "put it back" inside the main one. I also have docking disabled. What I plan to do is that child windows will "stick" on the sides of the main one.

So for this my local change seems it work fine, but I'm not sure if the fix that is needed for all other cases.

emoon commented

im_hippo

Just for reference this is what I'm hacking around with. I'm exploring to switch form Qt to bgfx/dear imgui for my musicplayer. This UI here is just a mock-up, but have the ability now to use multiple windows which is something I really needed and it works good in my case as I always have everything "floating"

@rokups could you check on Daniel’s suggestion to rework the linked code above and see if we can rely on the callback values instead of the explicit getter call?

We still can not drag a window outside of screen rect using glfwSetWindowPos() and callback correctly reports window position as "stuck" at the edge, however if window is moved outside of screen bounds using meta|alt+drag WM shortcut - callback does report correct positions. Seems like we have a path to better handling this situation, until SDL/GLFW produce a fix allowing to drag windows outside of screen bounds. 👍🏻

exuvo commented

We still can not drag a window outside of screen rect using glfwSetWindowPos() and callback correctly reports window position as "stuck" at the edge, however if window is moved outside of screen bounds using meta|alt+drag WM shortcut - callback does report correct positions. Seems like we have a path to better handling this situation, until SDL/GLFW produce a fix allowing to drag windows outside of screen bounds. 👍🏻

I'm not sure if this has been fixed since your comment but i don't seem to have any problems with dragging main viewport window or platform windows outside my monitors visible area. Maybe i misunderstand what the problem is?

Using GLFW backend patched to handle multiple main viewports. On Arch Linux with X and openbox window manager.

I had to adopt the sdl backend code for the mouseglobalstate and viewports disabled code path.

The problem was, the the window position by sdl is reported as x-offset 2560 - the global mouse coordinate was e.g. 956

It is possible that this is due to my xrandr config:

Screen 0: minimum 16 x 16, current 5120 x 1440, maximum 32767 x 32767
XWAYLAND27 connected 2560x1440+0+0 (0x24) normal (normal left inverted right x axis y axis) 600mm x 340mm
	Identifier: 0x6d3
	Timestamp:  38592
	Subpixel:   unknown
	Gamma:      1.0:1.0:1.0
	Brightness: 0.0
	Clones:    
	CRTC:       1
	CRTCs:      1
	Transform:  1.000000 0.000000 0.000000
	            0.000000 1.000000 0.000000
	            0.000000 0.000000 1.000000
	           filter: 
	non-desktop: 0 
		supported: 0, 1
  2560x1440 (0x24) 312.000MHz -HSync +VSync *current +preferred
        h: width  2560 start 2752 end 3024 total 3488 skew    0 clock  89.45KHz
        v: height 1440 start 1443 end 1448 total 1493           clock  59.91Hz
XWAYLAND28 connected primary 2560x1440+2560+0 (0x24) normal (normal left inverted right x axis y axis) 600mm x 340mm
	Identifier: 0x6d5
	Timestamp:  38592
	Subpixel:   unknown
	Gamma:      1.0:1.0:1.0
	Brightness: 0.0
	Clones:    
	CRTC:       0
	CRTCs:      0
	Transform:  1.000000 0.000000 0.000000
	            0.000000 1.000000 0.000000
	            0.000000 0.000000 1.000000
	           filter: 
	non-desktop: 0 
		supported: 0, 1
  2560x1440 (0x24) 312.000MHz -HSync +VSync *current +preferred
        h: width  2560 start 2752 end 3024 total 3488 skew    0 clock  89.45KHz
        v: height 1440 start 1443 end 1448 total 1493           clock  59.91Hz
diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp
index f87393f5..b90eaff2 100644
--- a/backends/imgui_impl_sdl.cpp
+++ b/backends/imgui_impl_sdl.cpp
@@ -408,6 +408,16 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
             // Unlike local position obtained earlier this will be valid when straying out of bounds.
             int window_x, window_y;
             SDL_GetWindowPosition(mouse_window, &window_x, &window_y);
+            int display_index = SDL_GetWindowDisplayIndex(mouse_window);
+            SDL_Rect display_rect;
+            SDL_GetDisplayBounds(display_index, &display_rect);
+            SDL_Point mouse_coord_point;
+            mouse_coord_point.x = mouse_x_global;
+            mouse_coord_point.y = mouse_y_global;
+            if (!SDL_PointInRect(&mouse_coord_point, &display_rect)) {
+                windowX -= display_rect.x;
+                windowY -= display_rect.y;
+            }
             io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
         }
     }

Even if it works with my current monitor setup - it's most likely not correct. (also SDL function return values are not checked for errors here)

without this offset hack the application was started at SDL display 0 - but the mouse movement was only caught while being on display 1 (right next to SDL display 0)

EDIT:

the window (0:0) the mouse is hovering is on SDL display 0 (0:0:2560:1440), but the global mouse position is at 3646:769 - this looks like a bug in SDL for me. I will report it there. Weird thing is that the SDL display 1 has a x position of 2560 but is the left display. Not sure how to convert the mouse coordinates properly.

Hi, I'm getting some issues with the docking branch on Ubuntu X11.
I just run the example_glfw_opengl3.
The docking area appears to be offset when dragging over.
Sometimes the window cannot be moved before resized
Sometimes delete key does not work on text input

Version: 1.87
Branch: docking

Back-ends: OpenGL
Compiler: GCC 10.3.0
Operating System: Ubuntu 20.04

video

Hi, I have some issues on MacOS with Vulkan backend.
When window is collapsed, ImGui::WindowSyncOwnedViewport() enable ImGuiViewportFlags_NoRendererClear flag, and platform window not clearing

void ImGui::WindowSyncOwnedViewport(...) {
    ...
    // We can also tell the backend that clearing the platform window won't be necessary,
    // as our window background is filling the viewport and we have disabled BgAlpha.
    // FIXME: Work on support for per-viewport transparency (#2766)
    if (!(window_flags & ImGuiWindowFlags_NoBackground))
        viewport_flags |= ImGuiViewportFlags_NoRendererClear;
    ...
Screen.Recording.2022-05-05.at.17.21.54.mov

If enable 'No background' checkbox in demo window, this issue appears too

Screen.Recording.2022-05-05.at.17.38.53.mov

Hi, I have some issues on MacOS with Vulkan backend. When window is collapsed, ImGui::WindowSyncOwnedViewport() enable ImGuiViewportFlags_NoRendererClear flag, and platform window not clearing

void ImGui::WindowSyncOwnedViewport(...) {
    ...
    // We can also tell the backend that clearing the platform window won't be necessary,
    // as our window background is filling the viewport and we have disabled BgAlpha.
    // FIXME: Work on support for per-viewport transparency (#2766)
    if (!(window_flags & ImGuiWindowFlags_NoBackground))
        viewport_flags |= ImGuiViewportFlags_NoRendererClear;
    ...

Screen.Recording.2022-05-05.at.17.21.54.mov

The multi-viewport feature is somehow causing my X server to crash.

Environment:

  • Arch Linux 5.15.81 LTS kernel
  • X Server 1.21.1.4
  • i3wm 4.21.1
  • Intel® HD Graphics 4000 (from an i5-3230M)
  • Dear ImGui commit 3ea0fad

Steps:

  1. Start one of the examples. I've tried example_glfw_opengl3, example_glfw_opengl2, example_sdl_opengl3 and example_sdl_opengl2.
  2. Pull one of the sub windows out of the main window.
  3. Put the windows that was pulled out into full screen mode (Mod+F keybind be default).
  4. Exit full-screen mode (Mod+F again).

On step 4 the whole X server crashes. In the X server log file I can find the following stack trace:

[  4330.703] (EE) Backtrace:
[  4330.704] (EE) 0: /usr/lib/Xorg (dri3_send_open_reply+0xdd) [0x5566b6bd9bad]
[  4330.705] (EE) 1: /usr/lib/libc.so.6 (__sigaction+0x50) [0x7f9f9f5a7a00]
[  4330.705] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  4330.706] (EE) 2: /usr/lib/xorg/modules/drivers/intel_drv.so (?+0x0) [0x7f9f9e7fc6ca]
[  4330.706] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  4330.706] (EE) 3: /usr/lib/xorg/modules/drivers/intel_drv.so (?+0x0) [0x7f9f9e88b558]
[  4330.707] (EE) unw_get_proc_name failed: no unwind info found [-10]
[  4330.707] (EE) 4: /usr/lib/xorg/modules/drivers/intel_drv.so (?+0x0) [0x7f9f9e801ffa]
[  4330.707] (EE) 5: /usr/lib/Xorg (DamageDamageRegion+0x1e0) [0x5566b6b4d650]
[  4330.707] (EE) 6: /usr/lib/Xorg (SetRootClip+0xb8f) [0x5566b6b2d49f]
[  4330.708] (EE) 7: /usr/lib/Xorg (SetRootClip+0x366c) [0x5566b6b2ff7c]
[  4330.708] (EE) 8: /usr/lib/Xorg (SetRootClip+0x4365) [0x5566b6b30c75]
[  4330.708] (EE) 9: /usr/lib/Xorg (FreeAllResources+0x4f2) [0x5566b6b22542]
[  4330.708] (EE) 10: /usr/lib/Xorg (MapWindow+0x164) [0x5566b6b280d4]
[  4330.709] (EE) 11: /usr/lib/Xorg (UpdateCurrentTime+0x8db) [0x5566b6af0c0b]
[  4330.709] (EE) 12: /usr/lib/Xorg (SProcXkbDispatch+0x280c) [0x5566b6aba057]
[  4330.710] (EE) 13: /usr/lib/libc.so.6 (__libc_init_first+0x90) [0x7f9f9f592290]
[  4330.711] (EE) 14: /usr/lib/libc.so.6 (__libc_start_main+0x8a) [0x7f9f9f59234a]
[  4330.711] (EE) 15: /usr/lib/Xorg (_start+0x25) [0x5566b6aba475]
[  4330.711] (EE) 
[  4330.711] (EE) Segmentation fault at address 0x20
[  4330.711] (EE) 
Fatal server error:
[  4330.711] (EE) Caught signal 11 (Segmentation fault). Server aborting

Based on the Intel graphics driver code in the stack trace I've tried the same using the discrete graphics card (from Nvidia) instead. There I cannot reproduce the crash.

Also worth noting: The crash only happens with the windows form the multi-viewport stuff. Fullscreening and restoring the main window of the example does not cause problems.

Now I'm just a user of Dear ImGui based software, so I don't really know what to do with this. It obviously seems to be Intel specific, but I don't know how to determine where the bug belongs to. As far as I can tell it could be Dear ImGui, i3, the X Server, the graphics driver or any combination of them.

Looks like tooltips/popups get recreated on contact with window border. I understand the intention behind this behaviour, but it breaks drag & drop functionality (example below). Is there an option to confine such widgets to platform window or force the behaviour from non-docking branch ?

Environment:

  • Arch Linux 6.2.9-arch1-1
  • GNOME 43.4
  • Mutter 43.4-1
  • Mesa 23.0.1 (Intel)

Software:

GLFW + OpenGL3 demo:

demo.webm

Unfortunately, mouse cursor is not captured by screencast software... I hope the example shows how dragged grid items disappear and how hard it is to initiate drag & drop on color widgets.

The same example works without problems on Windows 10, so I dedided to dicsuss the issue here

Window shakes when moving
Linux X11 xfce4 SDL2+vulkan

m3.webm

Reason: I guess there are internally multiple windows for a single window, and their positions vary, and the events are all passed in. the solution should filter out the messages of the correct window.

I guess this could be helpful if implemented in GLFW:
glfw/glfw#2437

i dont know how to do this on mac can someone help

@

This has been the main issue on Linux for 2 years (many reports above are variations of that) and somehow nobody went through to submit a proper fix for it yet (i am not a linux user).

There’s however a variant of this which is more puzzling, according to @rokups apparently when dragging windows partly outside of screen boundaries, the WM clamp them within boundaries but the corresponding getter functions in GLFW/SDL return the values requested in the setter functions (so without clamping). This may depend on the WM thought. @rokups could you check on Daniel’s suggestion to rework the linked code above and see if we can rely on the callback values instead of the explicit getter call?

If your fix works for you this is good news. How does the interaction feels? At which points does the mouse stops mapping to window position and can you extract it back properly?

Hi,

I'm interested in contributing to solving some of these problems. i've made a summary video of the issues I'm looking into atm:

Screencast.from.05-11-2024.02.19.13.PM.webm

To summarize:
Window/Viewport take charge in determining position and assume that our native window follows suit. This works on some platforms, but not on others. That leads to these behaviors:
- jittering of ForegroundDrawList content when hovering seperated viewports over each other (Maybe background too?).
- Foreground content keeps moving even though the viewport is clamped to the desktop.
- Interacting with viewports that have clamped to a desktop edge breaks because the window is assumed to be in a different position.

I tried reproducing this problem with the demo using a (linux, SDL, opengl) and a (linux, glfw, opengl) config and the jittery part is almost completely non-existent for SDL. I looked into the window positioning code and SDL will actually wait for the window manager to accept the new position before returning, glfw does not, explaining the difference there.

What I haven't been able to figure out yet, is why the window content is always positioned correctly, but the Foreground content is not. I expect it would be either both or neither since it all comes down to rendering on a viewport. If someone could enlighten me on that, that could be quite helpful.

I can think of 2 approaches here:

  1. I could create a repo of a demo windows build that emulates the linux behavior. Creating a reproducing scenario for the maintainers to work with.
  2. I could look into fixing it myself. But I'll need some support.

Hi,

I did some experimenting and have some things to share:

  • I was able to clamp the window to the desktop by changing UpdateMouseMovingWindowNewFrame() to use the PlatformIO callbacks to set and retrieve the window position in case of a viewportOwned window. I expect that similar changes would have to be made in different places as well. I'm a little on the fence about this change though, it kind of feels like some more structural change is needed here to have this happen in a single place.
  • The overlay desync looks like it will be hard to solve well. The latest time we can determine the actual position of the window is right before presenting, but the time of presenting is not the same as the time of drawing, while we're waiting for our frame to actually get rendered, the window can keep moving.
    -> I tried experimenting with replacing the DisplayPos from the ImDrawData with the actual window position at that time. That had interesting results (i could actually move the imgui window offscreen now as expected). But the imgui windows then desyncs from the real windows. I then tried to see if I could alleviate this by creating bigger windows with transparent framebuffers, but that window setting didn't seem to work at all for my window manager.
    -> An idea that I didn't experiment with at all yet. Would it be possible to use the native decoration (and style it?). It seems to be way more responsive then programmatically positioning a window.
    -> The SDL approach of waiting for the windows position to update is always an option I guess? But it might end up causing different (and worse) problems then the ones we have now.

It kind of feels like what you actually would want is a separate transparent overlay window on top the one that is going to be docked to, but then the transparent framebuffer thing would get in the way again. I guess it could be like an optional configuration thing that could be enabled when the support is there.

Not sure if any of this is new to you, but I'd rather overshare than undershare.