ocornut/imgui

If an auto-resized window contains another auto-resized child window, it cannot be centered correctly

Opened this issue · 2 comments

Version/Branch of Dear ImGui:

Version 1.92.2b

Back-ends:

Any (imgui_impl_sdl3.cpp + imgui_impl_sdlrenderer3.cpp)

Compiler, OS:

Any

Full config/build information:

No response

Details:

If an auto-resized window contains another auto-resized child window, it cannot be correctly centered with SetNextWindowPos (on appearing; when the window size is unknown).

Screenshots/Video:

Image

Minimal, Complete and Verifiable Example code:

static void issue() {
    static bool open = false;
    if (ImGui::Begin("Control", 0, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) {
        ImGui::Checkbox("Issue window", &open);
    }
    ImGui::End();

    if (open) {
        // Window-centering doesn't work in this case (auto-resized parent window + auto-resized child window).
        ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));

        if (ImGui::Begin("Issue", &open, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings)) {
            ImGui::Button("Settings");
            // Background:
            // Using child window for scrollable area with fixed height.
            // Using ImGuiChildFlags_AutoResizeX to avoid complex size calculation.
            if (ImGui::BeginChild("For scroll area", ImVec2(0, 100), ImGuiChildFlags_AutoResizeX)) {
                ImGui::Text("1234567890abcdefghijklmnopqrstuvwxyz");
                ImGui::Button("Button", ImVec2(200, 200));
            }
            ImGui::EndChild();
        }
        ImGui::End();
    }
}

Impact: to workaround this, I have to calculate size manually in my project.
Image

Like #8959, this may not be easy to fix. However, if so, please document this behavior.

if (ImGui::Begin("Issue", &open, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
{
    static int open_frame_count = 0;
    open_frame_count++;
    if (open_frame_count < 5)
        IMGUI_DEBUG_LOG("Main  Appearing %d, Size %.2f, %.2f\n", ImGui::IsWindowAppearing(), ImGui::GetWindowSize().x, ImGui::GetWindowSize().y);
    [...]
    if (ImGui::BeginChild("For scroll area", ImVec2(0, 100), ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_Borders))
    {
        if (open_frame_count < 5)
            IMGUI_DEBUG_LOG("Child Appearing %d, Size %.2f, %.2f\n", ImGui::IsWindowAppearing(), ImGui::GetWindowSize().x, ImGui::GetWindowSize().y);

Output

[00079] Main  Appearing 1, Size 24.00, 52.00    <-- resizing appears here.
[00079] Child Appearing 1, Size 24.00, 100.00
[00080] Main  Appearing 0, Size 124.00, 186.00 <-- becomes visible
[00080] Child Appearing 0, Size 421.00, 100.00
[00081] Main  Appearing 0, Size 445.00, 186.00
[00081] Child Appearing 0, Size 421.00, 100.00
[00082] Main  Appearing 0, Size 445.00, 186.00
[00082] Child Appearing 0, Size 421.00, 100.00

The workaround would be to center for another frame.

The more logical and general workaround would be that the Child window could somehow report that it is currently resizing to the parent with _AlwaysAutoResize, which would delay main window appearing for longer. But I am not sure there is a definitive and correct heuristic to decide that a child expected resizing would influence its parent. Hypothetically something like this:

[00079] Main  Appearing 1, Size 24.00, 52.00
[00079] Child Appearing 1, Size 24.00, 100.00 <--- report still appearing and resizing
[00080] Main  Appearing 0, Size 124.00, 186.00 <---- say hidden, mark as Appearing again
[00080] Child Appearing 0, Size 421.00, 100.00 <---- we know size
[00081] Main  Appearing 0, Size 445.00, 186.00 <--- becomes visible
[00081] Child Appearing 0, Size 421.00, 100.00
[00082] Main  Appearing 0, Size 445.00, 186.00
[00082] Child Appearing 0, Size 421.00, 100.00

But I worry it would come with a few side effects and traps to avoid.

However, if so, please document this behavior.

I don't know how to reasonably "document" this in a way which would be found by people affected.
It a result of first principles of how dear imgui works but there are endless combinations. In fact, it's probable that the exact same thing was reported already and you didn't find it (which is normal, given it is not simple to narrow down the problem to a simple keyword).

You have been, and you will be frequently bitten by auto-resizing problems.
They are not easy to solve in the context of a single-pass IMGUI system.
I personally suggest you should use less auto-sizing, e.g. in this case outer window may not need auto-resizing.