From 4d46383100145703fe3243a609cb67a6eb816452 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Mar 2018 20:10:40 +0100 Subject: [PATCH] Viewport: Coupling non-main viewport to one window. Viewport name derived from the window. Added ImGuiConfigFlags_PlatformNoTaskBar, off by default (aka re-established task-bars by default for now). (#1542) --- examples/directx10_example/main.cpp | 1 + examples/directx11_example/main.cpp | 1 + examples/imgui_impl_glfw.cpp | 4 +-- examples/imgui_impl_sdl2.cpp | 3 ++- examples/imgui_impl_win32.cpp | 9 ++++--- examples/opengl3_example/main.cpp | 1 + examples/sdl_opengl3_example/main.cpp | 1 + examples/sdl_vulkan_example/main.cpp | 1 + examples/vulkan_example/main.cpp | 1 + imgui.cpp | 36 ++++++++++++++++++--------- imgui.h | 17 +++++++------ imgui_internal.h | 10 +++++--- 12 files changed, 55 insertions(+), 30 deletions(-) diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 2e3f5dd35..811cda708 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -116,6 +116,7 @@ int main(int, char**) ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_EnableViewports; + io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplWin32_Init(hwnd); diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 81e85a352..d333f61cb 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -139,6 +139,7 @@ int main(int, char**) ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_EnableViewports; + io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplWin32_Init(hwnd); diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index bcb7ff888..6b520ba26 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -317,7 +317,6 @@ static void ImGui_ImplGlfw_CreateViewport(ImGuiViewport* viewport) data->Window = glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", NULL, share_window); data->WindowOwned = true; viewport->PlatformHandle = (void*)data->Window; - viewport->Name = NULL; ImGui_ImplGlfw_InstallCallbacks(data->Window); } @@ -358,7 +357,8 @@ static void ImGui_ImplGlfw_ShowWindow(ImGuiViewport* viewport) #if defined(_WIN32) // GLFW hack: Hide icon from task bar HWND hwnd = glfwGetWin32Window(data->Window); - if (viewport->Flags & ImGuiViewportFlags_NoDecoration) + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_PlatformNoTaskBar) { LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); ex_style &= ~WS_EX_APPWINDOW; diff --git a/examples/imgui_impl_sdl2.cpp b/examples/imgui_impl_sdl2.cpp index 7cd47f633..28a06d89a 100644 --- a/examples/imgui_impl_sdl2.cpp +++ b/examples/imgui_impl_sdl2.cpp @@ -316,7 +316,8 @@ static void ImGui_ImplSDL2_ShowWindow(ImGuiViewport* viewport) // SDL hack: Hide icon from task bar // Note: SDL 2.0.6+ has a SDL_WINDOW_SKIP_TASKBAR flag which is supported under Windows but the way it create the window breaks our seamless transition. - if (viewport->Flags & ImGuiViewportFlags_NoDecoration) + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_PlatformNoTaskBar) { LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); ex_style &= ~WS_EX_APPWINDOW; diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 7537aa8e4..1c82cb710 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -291,15 +291,18 @@ static void ImGui_ImplWin32_CreateViewport(ImGuiViewport* viewport) ImGuiPlatformDataWin32* data = IM_NEW(ImGuiPlatformDataWin32)(); viewport->PlatformUserData = data; - if (viewport->Flags & ImGuiViewportFlags_NoDecoration) + ImGuiIO& io = ImGui::GetIO(); + bool no_decoration = (viewport->Flags & ImGuiViewportFlags_NoDecoration) != 0; + bool no_task_bar = (io.ConfigFlags & ImGuiConfigFlags_PlatformNoTaskBar) != 0; + if (no_decoration) { data->DwStyle = WS_POPUP; - data->DwExStyle = 0; + data->DwExStyle = no_task_bar ? WS_EX_TOOLWINDOW : WS_EX_APPWINDOW; } else { data->DwStyle = WS_OVERLAPPEDWINDOW; - data->DwExStyle = WS_EX_TOOLWINDOW; + data->DwExStyle = no_task_bar ? WS_EX_TOOLWINDOW : WS_EX_APPWINDOW; } // Create window diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 197865594..0f943a9ae 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -36,6 +36,7 @@ int main(int, char**) ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_EnableViewports; + io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index f1fdf7a81..99dc3b956 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -38,6 +38,7 @@ int main(int, char**) ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_EnableViewports; + io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplSDL2_Init(window, gl_context); diff --git a/examples/sdl_vulkan_example/main.cpp b/examples/sdl_vulkan_example/main.cpp index cea829c5d..d896b8391 100644 --- a/examples/sdl_vulkan_example/main.cpp +++ b/examples/sdl_vulkan_example/main.cpp @@ -345,6 +345,7 @@ int main(int, char**) ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_EnableViewports; + io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplVulkan_InitInfo init_info = {}; diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 115227f7a..fbec7a6de 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -354,6 +354,7 @@ int main(int, char**) ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_EnableViewports; + io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplVulkan_InitInfo init_info = {}; diff --git a/imgui.cpp b/imgui.cpp index 810c42f99..f5949408f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3269,7 +3269,7 @@ static void ImGui::UpdateMovingWindowDropViewport(ImGuiWindow* window) { // Create new viewport ImVec2 os_pos = ConvertViewportPosToOsDesktopPos(window->Pos, window->Viewport); - ImGuiViewport* viewport = Viewport(window->ID, 0, os_pos, window->Size); + ImGuiViewport* viewport = Viewport(window, window->ID, 0, os_pos, window->Size); SetWindowViewportTranslateToPreservePlatformPos(window, window->Viewport, viewport); } } @@ -3388,7 +3388,7 @@ static void ImGui::UpdateViewports() ImVec2 main_viewport_os_desktop_pos = ImVec2(0.0f, 0.0f); if ((g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) main_viewport_os_desktop_pos = g.IO.PlatformInterface.GetWindowPos(main_viewport); - Viewport(IMGUI_VIEWPORT_DEFAULT_ID, ImGuiViewportFlags_MainViewport | ImGuiViewportFlags_HostOtherWindows, main_viewport_os_desktop_pos, g.IO.DisplaySize); + Viewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, ImGuiViewportFlags_MainViewport | ImGuiViewportFlags_HostOtherWindows, main_viewport_os_desktop_pos, g.IO.DisplaySize); if (!(g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) { @@ -3454,6 +3454,7 @@ static void UpdatePlatformWindows() ImGuiViewport* viewport = g.Viewports[i]; if ((viewport->Flags & ImGuiViewportFlags_MainViewport) || (viewport->LastFrameActive < g.FrameCount)) continue; + IM_ASSERT(viewport->Window != NULL); viewport->PlatformRequestClose = false; // FIXME-PLATFORM @@ -3466,13 +3467,17 @@ static void UpdatePlatformWindows() g.IO.PlatformInterface.SetWindowPos(viewport, viewport->PlatformOsDesktopPos); g.IO.PlatformInterface.SetWindowSize(viewport, viewport->Size); - char name[20]; - sprintf(name, "Viewport_%08X", viewport->ID); - if (viewport->Name == NULL || strcmp(viewport->Name, name) != 0) + // Update title bar + const char* title_begin = viewport->Window->Name; + const char* title_end = ImGui::FindRenderedTextEnd(title_begin); + const ImGuiID title_hash = ImHash(title_begin, (int)(title_end - title_begin)); + if (viewport->LastNameHash != title_hash ) { - g.IO.PlatformInterface.SetWindowTitle(viewport, name); - ImGui::MemFree(viewport->Name); - viewport->Name = ImStrdup(name); + viewport->LastNameHash = title_hash; + char* title_displayed = ImStrdup(viewport->Window->Name); + title_displayed[title_end - title_begin] = 0; + g.IO.PlatformInterface.SetWindowTitle(viewport, title_displayed); + ImGui::MemFree(title_displayed); } if (is_new_window) @@ -4512,7 +4517,7 @@ void ImGui::SetCurrentViewport(ImGuiViewport* viewport) g.IO.PlatformInterface.BeginViewport(g.CurrentViewport); } -ImGuiViewport* ImGui::Viewport(ImGuiID id, ImGuiViewportFlags flags, const ImVec2& os_desktop_pos, const ImVec2& size) +ImGuiViewport* ImGui::Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFlags flags, const ImVec2& os_desktop_pos, const ImVec2& size) { ImGuiContext& g = *GImGui; IM_ASSERT(id != 0); @@ -4532,6 +4537,7 @@ ImGuiViewport* ImGui::Viewport(ImGuiID id, ImGuiViewportFlags flags, const ImVec } IM_ASSERT(viewport->Pos.y == 0.0f); + viewport->Window = window; viewport->Flags = flags; viewport->PlatformOsDesktopPos = os_desktop_pos; viewport->LastFrameActive = g.FrameCount; @@ -5940,8 +5946,8 @@ static void ImGui::UpdateWindowViewport(ImGuiWindow* window, bool window_pos_set { // Create an undecorated, temporary OS/platform window ImVec2 os_desktop_pos = ConvertViewportPosToOsDesktopPos(g.IO.MousePos - g.ActiveIdClickOffset, g.MouseViewport); - ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs; - ImGuiViewport* viewport = Viewport(window->ID, viewport_flags, os_desktop_pos, window->Size); + ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs; + ImGuiViewport* viewport = Viewport(window, window->ID, viewport_flags, os_desktop_pos, window->Size); window->Flags |= ImGuiWindowFlags_FullViewport | ImGuiWindowFlags_NoBringToFrontOnFocus; window->Viewport = viewport; created_viewport = true; @@ -5980,7 +5986,7 @@ static void ImGui::UpdateWindowViewport(ImGuiWindow* window, bool window_pos_set { if (window->ViewportOsDesktopPos.x != FLT_MAX && window->ViewportOsDesktopPos.y != FLT_MAX) { - ImGuiViewport* viewport = Viewport(window->ID, ImGuiViewportFlags_NoDecoration, window->ViewportOsDesktopPos, window->Size); + ImGuiViewport* viewport = Viewport(window, window->ID, ImGuiViewportFlags_NoDecoration, window->ViewportOsDesktopPos, window->Size); window->Flags |= ImGuiWindowFlags_FullViewport | ImGuiWindowFlags_NoBringToFrontOnFocus; window->Viewport = viewport; created_viewport = true; @@ -6005,6 +6011,10 @@ static void ImGui::UpdateWindowViewport(ImGuiWindow* window, bool window_pos_set window->Flags |= ImGuiWindowFlags_FullViewport | ImGuiWindowFlags_NoBringToFrontOnFocus; } + // If the OS window has a title bar, hide our imgui title bar + if ((window->Flags & ImGuiWindowFlags_FullViewport) && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration)) + window->Flags |= ImGuiWindowFlags_NoTitleBar; + // Disable rounding for the window if (window->Viewport != main_viewport) window->WindowRounding = 0.0f; @@ -13933,6 +13943,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (ImGui::TreeNode((void*)(intptr_t)viewport->ID, "Viewport #%d, ID: 0x%08X, DrawLists: %d, Size: (%.0f,%.0f)", i, viewport->ID, draw_data->Layers[0].Size, viewport->Size.x, viewport->Size.y)) { ImGui::BulletText("Pos: (%.0f,%.0f)", viewport->Pos.x, viewport->Pos.y); + ImGui::BulletText("Flags: 0x%04X", viewport->Flags); + ImGui::BulletText("PlatformOsDesktopPos: (%.0f,%.0f)", viewport->PlatformOsDesktopPos.x, viewport->PlatformOsDesktopPos.y); for (int draw_list_i = 0; draw_list_i < viewport->DrawDataBuilder.Layers[0].Size; draw_list_i++) Funcs::NodeDrawList(NULL, viewport->DrawDataBuilder.Layers[0][draw_list_i], "DrawList"); ImGui::TreePop(); diff --git a/imgui.h b/imgui.h index 7b4a53970..a31a7b1fe 100644 --- a/imgui.h +++ b/imgui.h @@ -779,16 +779,17 @@ enum ImGuiConfigFlags_ // [BETA] Viewports ImGuiConfigFlags_EnableViewports = 1 << 4, // Viewport enable flags (require both ImGuiConfigFlags_PlatformHasViewports + ImGuiConfigFlags_RendererHasViewports set by the respective back-ends) - ImGuiConfigFlags_PlatformHasViewports = 1 << 5, // Back-end Platform supports multiple viewports - ImGuiConfigFlags_PlatformHasMouseHoveredViewport = 1 << 6, // Back-end Platform supports setting io.MouseHoveredViewport to the viewport directly under the mouse _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag and _REGARDLESS_ of whether another viewport is focused and may be capturing the mouse. This information is _NOT EASY_ to provide correctly with most high-level engines. Don't see this without studying how the examples/ back-end handle it. - ImGuiConfigFlags_PlatformHasWantMoveMouseSupport = 1 << 7, // Back-end Platform supports io.WantMoveMouse request by updating the OS mouse cursor position (currently only used by ImGuiConfigFlags_NavMoveMouse feature, will be useful for widgets teleporting/wrapping the cursor) - ImGuiConfigFlags_PlatformHasWindowAlpha = 1 << 8, // Back-end Platform supports transparent windows - ImGuiConfigFlags_RendererHasViewports = 1 << 9, // Back-end Renderer supports multiple viewports + ImGuiConfigFlags_PlatformNoTaskBar = 1 << 5, + ImGuiConfigFlags_PlatformHasViewports = 1 << 6, // Back-end Platform supports multiple viewports + ImGuiConfigFlags_PlatformHasMouseHoveredViewport = 1 << 7, // Back-end Platform supports setting io.MouseHoveredViewport to the viewport directly under the mouse _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag and _REGARDLESS_ of whether another viewport is focused and may be capturing the mouse. This information is _NOT EASY_ to provide correctly with most high-level engines. Don't see this without studying how the examples/ back-end handle it. + ImGuiConfigFlags_PlatformHasWantMoveMouseSupport = 1 << 8, // Back-end Platform supports io.WantMoveMouse request by updating the OS mouse cursor position (currently only used by ImGuiConfigFlags_NavMoveMouse feature, will be useful for widgets teleporting/wrapping the cursor) + ImGuiConfigFlags_PlatformHasWindowAlpha = 1 << 9, // Back-end Platform supports transparent windows + ImGuiConfigFlags_RendererHasViewports = 1 << 10, // Back-end Renderer supports multiple viewports // Platform Info (free of use, for user/application convenience) - ImGuiConfigFlags_IsSRGB = 1 << 10, // Back-end is SRGB-aware (Storage flag to allow your back-end to communicate to shared widgets. Not used by core ImGui) - ImGuiConfigFlags_IsTouchScreen = 1 << 11, // Back-end is using a touch screen instead of a mouse (Storage flag to allow your back-end to communicate to shared widgets. Not used by core ImGui) - ImGuiConfigFlags_IsOnScreenKeyboard = 1 << 12 // Back-end uses an on-screen keyboard when io.WantTextInput is set. + ImGuiConfigFlags_IsSRGB = 1 << 20, // Back-end is SRGB-aware (Storage flag to allow your back-end to communicate to shared widgets. Not used by core ImGui) + ImGuiConfigFlags_IsTouchScreen = 1 << 21, // Back-end is using a touch screen instead of a mouse (Storage flag to allow your back-end to communicate to shared widgets. Not used by core ImGui) + ImGuiConfigFlags_IsOnScreenKeyboard = 1 << 22 // Back-end uses an on-screen keyboard when io.WantTextInput is set. }; // Enumeration for PushStyleColor() / PopStyleColor() diff --git a/imgui_internal.h b/imgui_internal.h index 38ded77f1..3dc1b434d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -530,7 +530,8 @@ struct ImGuiViewport ImGuiViewportFlags Flags; int LastFrameActive; int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef - char* Name; // Name (OPTIONAL) + ImGuiID LastNameHash; + ImGuiWindow* Window; ImVec2 Pos; // Position in imgui virtual space (Pos.y == 0.0) ImVec2 Size; ImDrawData DrawData; @@ -538,14 +539,15 @@ struct ImGuiViewport // [Optional] OS/Platform Layer data. This is to allow the creation/manipulate of multiple OS/Platform windows. Not all back-ends will allow this. ImVec2 PlatformOsDesktopPos; // Position in OS desktop/native space + float PlatformDpiScale; // FIXME-DPI: Unused void* PlatformUserData; // void* to hold custom data structure for the platform (e.g. windowing info, render context) void* PlatformHandle; // void* for FindViewportByPlatformHandle(). (e.g. HWND, GlfwWindow*) bool PlatformRequestClose; // Platform window requested closure bool PlatformRequestResize; // Platform window requested resize void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. framebuffer) - ImGuiViewport(ImGuiID id, int idx) { ID = id; Idx = idx; Flags = 0; LastFrameActive = LastFrameAsRefViewport = -1; Name = NULL; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestResize = false; RendererUserData = NULL; } - ~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); if (Name) ImGui::MemFree(Name); } + ImGuiViewport(ImGuiID id, int idx) { ID = id; Idx = idx; Flags = 0; LastFrameActive = LastFrameAsRefViewport = -1; LastNameHash = 0; Window = NULL; PlatformDpiScale = 1.0f; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestResize = false; RendererUserData = NULL; } + ~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); } ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } float GetNextX() const { const float SPACING = 4.0f; return Pos.x + Size.x + SPACING; } }; @@ -1084,7 +1086,7 @@ namespace ImGui IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). // Viewports - IMGUI_API ImGuiViewport* Viewport(ImGuiID id, ImGuiViewportFlags flags, const ImVec2& os_desktop_pos, const ImVec2& size); // os_desktop_pos allows imgui to reposition windows relative to each order when moving from one viewport to the other. + IMGUI_API ImGuiViewport* Viewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFlags flags, const ImVec2& os_desktop_pos, const ImVec2& size); // os_desktop_pos allows imgui to reposition windows relative to each order when moving from one viewport to the other. inline ImVector&GetViewports() { return GImGui->Viewports; } inline ImGuiViewport* GetMainViewport() { return GImGui->Viewports[0]; } IMGUI_API ImGuiViewport* FindViewportByID(ImGuiID id);