Skip to content

Commit adc72a6

Browse files
committed
feat: viewports feature — panels detach into real OS windows
New independent `viewports` feature (usually combined with docking): - core exports GetMainViewport/UpdatePlatformWindows/ RenderPlatformWindowsDefault/SetNextWindowPos + ConfigFlags_ViewportsEnable (gated by MCPP_FEATURE_VIEWPORTS). - imgui.app facade enables ViewportsEnable and renders platform windows each frame (with GL context backup/restore); GlfwOpenGL3 gains GetCurrentContext. - docking example requests ["docking", "viewports"] and spawns a 'Detached' panel outside the main window — verified: a separate OS window appears in the X window tree and renders (drag back inside to re-dock). Default (feature-off) build/tests unchanged.
1 parent 0ed45d0 commit adc72a6

7 files changed

Lines changed: 57 additions & 4 deletions

File tree

examples/docking/mcpp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ description = "Dockable-windows demo using the imgui `docking` feature"
55
license = "MIT"
66

77
[dependencies]
8-
imgui = { path = "../..", features = ["docking"] }
8+
imgui = { path = "../..", features = ["docking", "viewports"] }

examples/docking/src/main.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
// Docking demo — `imgui = { ..., features = ["docking"] }`.
1+
// Docking + multi-viewport demo —
2+
// imgui = { ..., features = ["docking", "viewports"] }
23
//
34
// On the first frame, DockBuilder splits the dockspace into an IDE-style
45
// layout (Scene | Viewport | Inspector, Console at the bottom). Every pane is
5-
// a real dock node: drag any tab to re-split, stack, or float it — the
6-
// docking previews/overlays appear while dragging.
6+
// a real dock node: drag any tab to re-split, stack, or float it.
7+
// With `viewports`, drag a tab OUTSIDE the main window and it detaches into
8+
// its own OS window; the "Detached" panel below starts outside on purpose.
79
import imgui.core;
810
import imgui.app;
911

@@ -45,5 +47,16 @@ int main() {
4547
ImGui::Begin("Console");
4648
ImGui::TextUnformatted("Log pane (bottom split).");
4749
ImGui::End();
50+
51+
// Starts OUTSIDE the main window: with `viewports` this is a real,
52+
// separate OS window from the very first frame.
53+
const auto* main_vp = ImGui::GetMainViewport();
54+
ImGui::SetNextWindowPos(
55+
ImVec2{main_vp->Pos.x + main_vp->Size.x + 60.0f, main_vp->Pos.y + 80.0f},
56+
ImGui::Cond_FirstUseEver);
57+
ImGui::Begin("Detached");
58+
ImGui::TextUnformatted("I live in my own OS window.");
59+
ImGui::TextUnformatted("Drag me back inside to re-dock.");
60+
ImGui::End();
4861
});
4962
}

mcpp.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ default = []
2727
# docking: export the Dock* API surface and auto-enable
2828
# ImGuiConfigFlags_DockingEnable in the imgui.app facade.
2929
docking = []
30+
# viewports: ImGui windows dragged outside the main window detach into real
31+
# OS windows (multi-viewport). Usually combined with docking.
32+
viewports = []
3033

3134
[dependencies]
3235
compat.imgui = "1.92.8-docking"

src/app.cppm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ export namespace ImGui::App {
5757
// `docking` feature: enable dockable windows out of the box.
5858
ImGui::GetIO().ConfigFlags |= ImGui::ConfigFlags_DockingEnable;
5959
#endif
60+
#ifdef MCPP_FEATURE_VIEWPORTS
61+
// `viewports` feature: windows dragged outside the main window
62+
// detach into real OS windows.
63+
ImGui::GetIO().ConfigFlags |= ImGui::ConfigFlags_ViewportsEnable;
64+
#endif
6065

6166
if (!Backend::Init(window)) {
6267
const auto error = Backend::LastError();
@@ -84,6 +89,15 @@ export namespace ImGui::App {
8489
Backend::ClearColor(0.10f, 0.10f, 0.12f, 1.0f);
8590
Backend::ClearColorBuffer();
8691
Backend::RenderDrawData(ImGui::GetDrawData());
92+
#ifdef MCPP_FEATURE_VIEWPORTS
93+
// Render the detached OS windows, then restore the main context.
94+
{
95+
auto* backup = Backend::GetCurrentContext();
96+
ImGui::UpdatePlatformWindows();
97+
ImGui::RenderPlatformWindowsDefault();
98+
Backend::MakeContextCurrent(backup);
99+
}
100+
#endif
87101
Backend::SwapBuffers(window);
88102
}
89103

src/backends/glfw_opengl3.cppm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ export namespace ImGui::Backend {
6262
GlfwPlatform::MakeContextCurrent(window);
6363
}
6464

65+
static Window* GetCurrentContext() {
66+
return GlfwPlatform::GetCurrentContext();
67+
}
68+
6569
static void SwapInterval(int interval) {
6670
GlfwPlatform::SwapInterval(interval);
6771
}

src/backends/platform_glfw.cppm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ export namespace ImGui::Backend {
7171
glfwMakeContextCurrent(window);
7272
}
7373

74+
static Window* GetCurrentContext() {
75+
return glfwGetCurrentContext();
76+
}
77+
7478
static FbSize FramebufferSize(Window* window) {
7579
int width = 0;
7680
int height = 0;

src/core.cppm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,18 @@ export namespace ImGui {
6565
inline constexpr ::ImGuiDir Dir_Down = ::ImGuiDir_Down;
6666
}
6767
#endif
68+
69+
// Multi-viewport surface — gated by the `viewports` feature: ImGui windows
70+
// dragged (or positioned) outside the main window become real OS windows.
71+
#ifdef MCPP_FEATURE_VIEWPORTS
72+
export using ImGuiViewport = ::ImGuiViewport;
73+
74+
export namespace ImGui {
75+
using ::ImGui::GetMainViewport;
76+
using ::ImGui::UpdatePlatformWindows;
77+
using ::ImGui::RenderPlatformWindowsDefault;
78+
using ::ImGui::SetNextWindowPos;
79+
80+
inline constexpr int ConfigFlags_ViewportsEnable = ::ImGuiConfigFlags_ViewportsEnable;
81+
}
82+
#endif

0 commit comments

Comments
 (0)