Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows undocks from Dockspace when changing tabs #6505

Closed
hka opened this issue Jun 9, 2023 · 3 comments
Closed

Windows undocks from Dockspace when changing tabs #6505

hka opened this issue Jun 9, 2023 · 3 comments
Labels
docking label/id and id stack implicit identifiers, pushid(), id stack tabs tab bars, tabs

Comments

@hka
Copy link

hka commented Jun 9, 2023

Version/Branch of Dear ImGui:

Version: 1.89.7 WIP
Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: custom
Compiler: gcc 10.2.1
Operating System: Debian 11

My Issue/Question:

Windows get undocked when changing tab even when I call DockSpace with ImGuiDockNodeFlags_KeepAliveOnly for the hidden tabs. I have looked at issues #2599 and #2720 and I think I do as it says in those issues. Am I doing something wrong, or what should I do to make a DockSpace stay put inside a tab? I have mostly picked parts from imgui_demo.cpp

Screenshots/Video
A build off my code:
https://hka.github.io/test-imgui/
press the plus to create a second tab, press "Menu/New workspace" to get a window to dock, dock it and change tab.

Standalone, minimal, complete and verifiable example:
Not complete really but I guess this is the part where I do something wrong, for the rest of the code see
https://github.com/hka/test-imgui/blob/master/src/simple.cpp
not sure how make a more minimal example, very new to imgui.

  if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
  {
    if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
    {
      active_tabs.push_back(next_tab_id++); // Add new tab
    }

    // Submit our regular tabs
    for (int n = 0; n < active_tabs.Size; )
    {
      bool open = true;
      char name[16];
      snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]);

      if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
      {
        ImGuiIO& io = ImGui::GetIO();
        if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
        {
          std::string d_id = "MyDockSpace" + std::to_string(n);
          ImGuiID dockspace_id = ImGui::GetID(d_id.c_str());
          ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
        }
        ImGui::EndTabItem();
      }
      else
      {
        std::string d_id = "MyDockSpace" + std::to_string(n);
        ImGuiID dockspace_id = ImGui::GetID(d_id.c_str());
        ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_KeepAliveOnly);
      }

      if (!open)
        active_tabs.erase(active_tabs.Data + n);
      else
        n++;
    }

    ImGui::EndTabBar();
  }
@PathogenDavid
Copy link
Contributor

Thank you for filling out the whole issue template and doing your due diligence!

This is happening because the full ID of your dockspace is different depending on whether the tab item has focus. Dear ImGui IDs are stack-based, you can read more about this in this FAQ entry.

Basically when tab 0000 has focus, your dockspace has the full ID of [Dear ImGui Demo][MyTabBar][0000][MyDockSpace0]. When it loses focus, you're calling GetID in a different ID scope resulting in the full ID of [Dear ImGui Demo][MyTabBar][MyDockSpace0]. (If you inspect the raw value of dockspace_id in each branch you'll find that they're different.


The easiest solution in your case would be to calculate dockspace_id outside of the BeginTabItem branch (which by extension is outside of the tab item's ID scope.) IE:

std::string d_id = "MyDockSpace" + std::to_string(n);
ImGuiID dockspace_id = ImGui::GetID(d_id.c_str());

if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
{
  ImGuiIO& io = ImGui::GetIO();
  if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
  {
    ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
  }
  ImGui::EndTabItem();
}
else
{
  ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_KeepAliveOnly);
}

Some alternate solutions would be:

  • Pass ImGuiTabItemFlags_NoPushId to BeginTabItem (could result in ID collisions between tabs if you ever add more than just the dockspace -- Use PushID/PopID to explicitly create a scope.)
  • Manually call PushID(name)...PopID() around the KeepAliveOnly dockspace.
  • Manually calculate a global ID using ImHashStr (an internal API)

@hka
Copy link
Author

hka commented Jun 9, 2023

Ah! I see!

I had just narrowed it down to being related to the dockspace_id, but didn't understand why. I change so I only used GetID once and then stored the value for each tab and saved the value, which solved the problem. With your explanation I also understand why :)

If anyone else happens upon this, here is my working code:
https://github.com/hka/test-imgui/blob/9d615810079d0d2457a4c02661ab44d1e70ed599/src/simple.cpp

Thanks for the help!

@hka hka closed this as completed Jun 9, 2023
@ocornut
Copy link
Owner

ocornut commented Jun 12, 2023

Thanks David for the help!

Just for clarify: DockSpace() is already a no-op if ImGuiConfigFlags_DockingEnable is not set, so you don't need to test for this.

@ocornut ocornut added docking label/id and id stack implicit identifiers, pushid(), id stack labels Jun 12, 2023
@ocornut ocornut changed the title Windows undocks when changing tabs Windows undocks from Dockspace when changing tabs Jun 12, 2023
@ocornut ocornut added the tabs tab bars, tabs label Jun 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docking label/id and id stack implicit identifiers, pushid(), id stack tabs tab bars, tabs
Projects
None yet
Development

No branches or pull requests

3 participants