ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
60.92k stars 10.29k forks source link

SetNextWindowRefreshPolicy issues #7797

Open VerySmallRoach opened 3 months ago

VerySmallRoach commented 3 months ago

Version/Branch of Dear ImGui:

Version 1.90.9, Branch: master

Back-ends:

Win32 + DirectX 9

Compiler, OS:

MSVC 2019

Full config/build information:

No response

Details:

Please note that I realize this is experimental stuff and I don't have an active need in this functionality. I just happen to play around it and thought to share some feedback. So deal with it at your pace, perhaps you are already aware of these limitations.

  1. Following code creates two windows, both showing incrementing counter. First window stops updating counter once it goes out of focus, as expected with TryToAvoidRefresh. In second window, however, counter disappears entirely, probably because Begin returns false and BeginChild stops being called. So as of now SetNextWindowRefreshPolicy is only useful for windows without any children.
    static int count = 0;
    count++;
    ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags_RefreshOnFocus | ImGuiWindowRefreshFlags_RefreshOnHover | ImGuiWindowRefreshFlags_TryToAvoidRefresh);
    if (ImGui::Begin("first")) {
        ImGui::Text(std::to_string(count).c_str());
    }
    ImGui::End();

    ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags_RefreshOnFocus | ImGuiWindowRefreshFlags_RefreshOnHover | ImGuiWindowRefreshFlags_TryToAvoidRefresh);
    if (ImGui::Begin("second")) {
        if (ImGui::BeginChild("child")) {
            ImGui::Text(std::to_string(count).c_str());
        }
        ImGui::EndChild();
    }
    ImGui::End();
  1. Similar issue with popups: popup opens but disappears after mouse is moved to click it.
    ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags_RefreshOnFocus | ImGuiWindowRefreshFlags_RefreshOnHover | ImGuiWindowRefreshFlags_TryToAvoidRefresh);
    if (ImGui::Begin("first")) {
        ImGui::Button("button");
        if (ImGui::BeginPopupContextItem()) {
            ImGui::Text("Popup");
            ImGui::EndPopup();
        }
    }
    ImGui::End();

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

No response

ocornut commented 3 months ago

Thanks for reporting. I have pushed a fix for the first issue. I don't yet know how to solve the second one.

ocornut commented 3 months ago

I have also pushed a fix for the second use case: 6864a7f

However, that popup case may be generalized further, even without popup:

ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags_RefreshOnFocus | ImGuiWindowRefreshFlags_RefreshOnHover | ImGuiWindowRefreshFlags_TryToAvoidRefresh);
if (ImGui::Begin("Window A"))
{
    ImGui::Text("%d", ImGui::GetFrameCount());

    ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags_RefreshOnFocus | 
ImGuiWindowRefreshFlags_RefreshOnHover | ImGuiWindowRefreshFlags_TryToAvoidRefresh);
    if (ImGui::Begin("Window B"))
    {
        ImGui::Text("%d", ImGui::GetFrameCount());
    }
    ImGui::End();
}
ImGui::End();

And this gets more tricky because whereas in the popup case, the nested popup can't exist when parent is focused, here they are two distinct windows. We would need to store an array of windows submitted within our begin stack next to window->DC.ChildWindows[], solely for use of marking them active with skiprefresh, which itself would be inconsistent with expected behavior. So, I don't know.

VerySmallRoach commented 3 months ago

At the very least case with Begin, unlike BeginChild/popup, could be solved by user by moving Begin call outside and manually controlling Window B visibility. Still a booby trap, but a booby trap that can be worked around. Don't really know what else to say, I'm not that familiar with ImGui to discuss edge cases that I've never encountered myself, let alone solutions to them. I'll leave to your discretion whenever to close this issue or keep it open.