Skip to content

Commit

Permalink
Multiple Host Windows Support
Browse files Browse the repository at this point in the history
Support to multiple hosting windows/viewports based on shared by
ocornut.
Last major issue resizing addition host windows was found and fixed by
@Patuti.
  • Loading branch information
fungos committed May 16, 2019
1 parent 4158cba commit 3e6fd15
Show file tree
Hide file tree
Showing 10 changed files with 609 additions and 114 deletions.
55 changes: 52 additions & 3 deletions examples/example_glfw_opengl2/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,32 @@ static void glfw_error_callback(int error, const char* description)
fprintf(stderr, "Glfw Error %d: %s\n", error, description);
}

void CreateAdditionalViewport(GLFWwindow* mainWindow, ImVector<ImGuiViewport*>& additionalHostViewports)
{
glfwWindowHint(GLFW_DECORATED, true);
GLFWwindow* w = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL2 example - additional host window", NULL, mainWindow);
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGuiViewport* v = platform_io.Platform_RegisterUserWindow(w);
glfwMakeContextCurrent(w);
//glfwSwapInterval(1); // Enable vsync
glfwMakeContextCurrent(mainWindow);
additionalHostViewports.push_back(v);
glfwShowWindow(w);
}

int main(int, char**)
{
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;

// flag to indicate whether main window should be displayed and used as a viewport
bool hasMainViewport = true;

// even if there's no main window we still need to create a hidden window to share the context
if (!hasMainViewport)
glfwWindowHint(GLFW_VISIBLE, 0);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL2 example", NULL, NULL);
if (window == NULL)
return 1;
Expand Down Expand Up @@ -81,13 +101,31 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);

ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
bool show_main_window = true;
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
ImVector<ImGuiViewport*> additionalHostViewports;

// Main loop
while (!glfwWindowShouldClose(window))
{
for (int i = 0; i < additionalHostViewports.Size; i++)
{
ImGuiViewport* v = additionalHostViewports[i];
GLFWwindow* w = (GLFWwindow *)v->PlatformHandle;
if (glfwWindowShouldClose(w))
{
ImGui::UnregisterPlatformWindow(v);
if (platform_io.Platform_DestroyWindow)
platform_io.Platform_DestroyWindow(v);
IM_DELETE(v);
glfwDestroyWindow(w);
additionalHostViewports.erase(additionalHostViewports.Data + i);
i--;
}
}
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
Expand All @@ -108,8 +146,8 @@ int main(int, char**)
{
static float f = 0.0f;
static int counter = 0;

ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
bool* popen = hasMainViewport ? NULL : &show_main_window;
ImGui::Begin("Hello, world!", popen); // Create a window called "Hello, world!" and append into it.

ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
Expand All @@ -122,7 +160,8 @@ int main(int, char**)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);

if (ImGui::Button("New Host Viewport"))
CreateAdditionalViewport(window, additionalHostViewports);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
Expand Down Expand Up @@ -161,10 +200,20 @@ int main(int, char**)
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
for (int i = 0; i < additionalHostViewports.Size; i++)
{
ImGuiViewport* v = additionalHostViewports[i];
if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(v, NULL);
if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(v, NULL);
if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(v, NULL);
if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(v, NULL);
}
glfwMakeContextCurrent(backup_current_context);
}

glfwSwapBuffers(window);
if (!show_main_window)
glfwSetWindowShouldClose(window, 1);
}

// Cleanup
Expand Down
57 changes: 53 additions & 4 deletions examples/example_glfw_opengl3/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,33 @@ static void glfw_error_callback(int error, const char* description)
fprintf(stderr, "Glfw Error %d: %s\n", error, description);
}

void CreateAdditionalViewport(GLFWwindow* mainWindow, ImVector<ImGuiViewport*>& additionalHostViewports)
{
glfwWindowHint(GLFW_DECORATED, true);
GLFWwindow* w = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL2 example - additional host window", NULL, mainWindow);
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGuiViewport* v = platform_io.Platform_RegisterUserWindow(w);
glfwMakeContextCurrent(w);
//glfwSwapInterval(1); // Enable vsync
glfwMakeContextCurrent(mainWindow);
additionalHostViewports.push_back(v);
glfwShowWindow(w);
}

int main(int, char**)
{
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;

// flag to indicate whether main window should be displayed and used as a viewport
bool hasMainViewport = true;

// even if there's no main window we still need to create a hidden window to share the context
if (!hasMainViewport)
glfwWindowHint(GLFW_VISIBLE, 0);

// Decide GL+GLSL versions
#if __APPLE__
// GL 3.2 + GLSL 150
Expand Down Expand Up @@ -124,13 +144,31 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);

ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
bool show_main_window = true;
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
ImVector<ImGuiViewport*> additionalHostViewports;

// Main loop
while (!glfwWindowShouldClose(window))
{
for (int i = 0; i < additionalHostViewports.Size; i++)
{
ImGuiViewport* v = additionalHostViewports[i];
GLFWwindow* w = (GLFWwindow *)v->PlatformHandle;
if (glfwWindowShouldClose(w))
{
ImGui::UnregisterPlatformWindow(v);
if (platform_io.Platform_DestroyWindow)
platform_io.Platform_DestroyWindow(v);
IM_DELETE(v);
glfwDestroyWindow(w);
additionalHostViewports.erase(additionalHostViewports.Data + i);
i--;
}
}
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
Expand All @@ -151,8 +189,8 @@ int main(int, char**)
{
static float f = 0.0f;
static int counter = 0;

ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
bool* popen = hasMainViewport ? NULL : &show_main_window;
ImGui::Begin("Hello, world!", popen); // Create a window called "Hello, world!" and append into it.

ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
Expand All @@ -165,7 +203,8 @@ int main(int, char**)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);

if (ImGui::Button("New Host Viewport"))
CreateAdditionalViewport(window, additionalHostViewports);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
Expand All @@ -188,7 +227,7 @@ int main(int, char**)
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

// Update and Render additional Platform Windows
// (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
// For this specific demo app we could also call glfwMakeContextCurrent(window) directly)
Expand All @@ -197,10 +236,20 @@ int main(int, char**)
GLFWwindow* backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
for (int i = 0; i < additionalHostViewports.Size; i++)
{
ImGuiViewport* v = additionalHostViewports[i];
if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(v, NULL);
if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(v, NULL);
if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(v, NULL);
if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(v, NULL);
}
glfwMakeContextCurrent(backup_current_context);
}

glfwSwapBuffers(window);
if (!show_main_window)
glfwSetWindowShouldClose(window, 1);
}

// Cleanup
Expand Down
71 changes: 68 additions & 3 deletions examples/example_sdl_opengl2/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@
#include <SDL.h>
#include <SDL_opengl.h>

ImGuiViewport* CreateAdditionalWindow(SDL_Window* mainWindow)
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();

SDL_GLContext backup_context = SDL_GL_GetCurrentContext();
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
SDL_GL_MakeCurrent(mainWindow, backup_context);
Uint32 window_flags = SDL_GetWindowFlags(mainWindow);
SDL_Window* w = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example - additional host window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
SDL_GL_MakeCurrent(w, backup_context);
ImGuiViewport* v = platform_io.Platform_RegisterUserWindow(w);
SDL_GL_SetSwapInterval(0);
SDL_GL_MakeCurrent(mainWindow, backup_context);

return v;
}

void DestroyAdditionalWindow(SDL_Window* w, ImGuiViewport* v)
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_UnregisterUserWindow(v);
SDL_DestroyWindow(w);
}

int main(int, char**)
{
// Setup SDL
Expand All @@ -22,13 +46,20 @@ int main(int, char**)
return -1;
}

// flag to indicate whether main window should be displayed and used as a viewport
bool hasMainViewport = true;

// Setup window
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
// even if there's no main window we still need to create a hidden window to share the context
int hidden = (hasMainViewport ? 0 : SDL_WINDOW_HIDDEN);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | hidden);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context);
Expand Down Expand Up @@ -76,9 +107,12 @@ int main(int, char**)
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);

ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
bool show_main_window = true;
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
ImVector<ImGuiViewport*> additionalHostViewports;

// Main loop
bool done = false;
Expand All @@ -95,6 +129,19 @@ int main(int, char**)
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
done = true;
for (int i = 0; i < additionalHostViewports.Size; i++)
{
ImGuiViewport* v = additionalHostViewports[i];
SDL_Window* w = (SDL_Window *)v->PlatformHandle;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(w))
{
DestroyAdditionalWindow(w, v);
additionalHostViewports.erase(additionalHostViewports.Data + i);
i--;
}
}
}

// Start the Dear ImGui frame
Expand All @@ -111,7 +158,8 @@ int main(int, char**)
static float f = 0.0f;
static int counter = 0;

ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
bool* popen = hasMainViewport ? NULL : &show_main_window;
ImGui::Begin("Hello, world!", popen); // Create a window called "Hello, world!" and append into it.

ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
Expand All @@ -124,7 +172,8 @@ int main(int, char**)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);

if (ImGui::Button("New Host Window"))
additionalHostViewports.push_back(CreateAdditionalWindow(window));
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
Expand Down Expand Up @@ -156,12 +205,28 @@ int main(int, char**)
SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
for (int i = 0; i < additionalHostViewports.Size; i++)
{
ImGuiViewport* v = additionalHostViewports[i];
if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(v, NULL);
if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(v, NULL);
if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(v, NULL);
if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(v, NULL);
}
SDL_GL_MakeCurrent(backup_current_window, backup_current_context);
}

SDL_GL_SwapWindow(window);
}

// Cleanup any other additional sample user windows created
for (int i = 0; i < additionalHostViewports.Size; i++)
{
ImGuiViewport* v = additionalHostViewports[i];
SDL_Window* w = (SDL_Window *)v->PlatformHandle;
DestroyAdditionalWindow(w, v);
}

// Cleanup
ImGui_ImplOpenGL2_Shutdown();
ImGui_ImplSDL2_Shutdown();
Expand Down
Loading

0 comments on commit 3e6fd15

Please sign in to comment.