From 3a7828de6b49b8ad7cdb8787fade5ab48277e8c7 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 9 Oct 2018 14:19:39 +0200 Subject: [PATCH 1/2] Viewport: Added ImGuiConfigFlags_ViewportsDecoration to re-enable platform decoration (#1542) --- docs/TODO.txt | 1 + imgui.cpp | 35 +++++++++++++++++++++-------------- imgui.h | 16 +++++++++------- imgui_demo.cpp | 4 +++- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/docs/TODO.txt b/docs/TODO.txt index 49706570..9b2893d3 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -281,6 +281,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - examples: move ImGui::NewFrame() out of the backend _NewFrame() ? - viewport: make it possible to have no main/hosting viewport + - viewport: with platform decoration enabled, platform may force constraint (e.g. minimum size) - viewport: use getfocus/setfocus api to synchronize imgui<>platform focus better (e.g imgui-side ctrl-tab can focus os window, OS initial setup and alt-tab can focus imgui window etc.) - viewport: store per-viewport/monitor DPI in .ini file so an application reload or main window changing DPI on reload can be properly patched for. - viewport: vulkan renderer implementation. diff --git a/imgui.cpp b/imgui.cpp index 8b35381f..0dfe9795 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3211,10 +3211,13 @@ void ImGui::NewFrame() { if ((g.IO.BackendFlags & ImGuiBackendFlags_PlatformHasViewports) && (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasViewports)) { - IM_ASSERT((g.FrameCount == 0 || g.FrameCount == g.FrameCountPlatformEnded) && "Forgot to call UpdatePlatformWindows() at the end of the previous frame?"); + IM_ASSERT((g.FrameCount == 0 || g.FrameCount == g.FrameCountPlatformEnded) && "Forgot to call UpdatePlatformWindows() in main loop after EndFrame()?"); IM_ASSERT(g.PlatformIO.Platform_CreateWindow != NULL && "Platform init didn't install handlers?"); IM_ASSERT(g.PlatformIO.Platform_DestroyWindow != NULL && "Platform init didn't install handlers?"); IM_ASSERT(g.PlatformIO.Platform_GetWindowPos != NULL && "Platform init didn't install handlers?"); + IM_ASSERT(g.PlatformIO.Platform_SetWindowPos != NULL && "Platform init didn't install handlers?"); + IM_ASSERT(g.PlatformIO.Platform_GetWindowSize != NULL && "Platform init didn't install handlers?"); + IM_ASSERT(g.PlatformIO.Platform_SetWindowSize != NULL && "Platform init didn't install handlers?"); IM_ASSERT((g.Viewports[0]->PlatformUserData != NULL || g.Viewports[0]->PlatformHandle != NULL) && "Platform init didn't setup main viewport."); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS IM_ASSERT(g.IO.RenderDrawListsFn == NULL); // Call ImGui::Render() then pass ImGui::GetDrawData() yourself to your render function! @@ -5028,7 +5031,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // Late create viewport, based on the assumption that with our calculations, the DPI will be known ahead (same as the DPI of the selection done in UpdateSelectWindowViewport) //ImGuiViewport* old_viewport = window->Viewport; - ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ((window->Flags & ImGuiWindowFlags_NoInputs) ? ImGuiViewportFlags_NoInputs : 0); + ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoFocusOnAppearing | ((window->Flags & ImGuiWindowFlags_NoInputs) ? ImGuiViewportFlags_NoInputs : 0); window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, viewport_flags); // FIXME-DPI @@ -7191,6 +7194,7 @@ static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 m return best_candidate; } +// Called in NewFrame() static void ImGui::UpdateViewports() { ImGuiContext& g = *GImGui; @@ -7413,7 +7417,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) { window->Viewport = FindViewportByID(window->ViewportId); if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX) - window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_NoDecoration); + window->Viewport = AddUpdateViewport(window, window->ID, window->ViewportPos, window->Size, ImGuiViewportFlags_None); } } @@ -7443,11 +7447,11 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) bool leave_host_viewport = has_viewport && !own_viewport && !window->Viewport->GetRect().Contains(window->Rect()); bool move_from_own_viewport = has_viewport && own_viewport && !(window->Viewport->Flags & ImGuiViewportFlags_NoInputs); if (!has_viewport || leave_host_viewport || move_from_own_viewport) - window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs); + window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs); } else if (GetWindowAlwaysWantOwnViewport(window)) { - window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoDecoration); + window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_None); } // Mark window as allowed to protrude outside of its viewport and into the current monitor @@ -7472,16 +7476,15 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) // Update flags window->ViewportOwned = (window == window->Viewport->Window); - if (window->ViewportOwned) - window->Viewport->Flags |= ImGuiViewportFlags_NoDecoration; // If the OS window has a title bar, hide our imgui title bar - if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration)) - window->Flags |= ImGuiWindowFlags_NoTitleBar; + //if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration)) + // window->Flags |= ImGuiWindowFlags_NoTitleBar; window->ViewportId = window->Viewport->ID; } +// Called by imgui at the end of the main loop, after EndFrame() void ImGui::UpdatePlatformWindows() { ImGuiContext& g = *GImGui; @@ -7515,13 +7518,17 @@ void ImGui::UpdatePlatformWindows() if (viewport->Size.x <= 0 || viewport->Size.y <= 0) continue; - // Update viewport flags + // Update common viewport flags for owned viewports if (viewport->Window != NULL) { - bool topmost = (viewport->Window->Flags & ImGuiWindowFlags_Tooltip) != 0; - bool no_task_bar_icon = (g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoTaskBarIcons) != 0 || (viewport->Window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0; - viewport->Flags = topmost ? (viewport->Flags | ImGuiViewportFlags_TopMost) : (viewport->Flags & ~ImGuiViewportFlags_TopMost); - viewport->Flags = no_task_bar_icon ? (viewport->Flags | ImGuiViewportFlags_NoTaskBarIcon) : (viewport->Flags & ~ImGuiViewportFlags_NoTaskBarIcon); + ImGuiViewportFlags flags = viewport->Flags & ~(ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration); + if (viewport->Window->Flags & ImGuiWindowFlags_Tooltip) + flags |= ImGuiViewportFlags_TopMost; + if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoTaskBarIcon) != 0 || (viewport->Window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) + flags |= ImGuiViewportFlags_NoTaskBarIcon; + if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (viewport->Window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) + flags |= ImGuiViewportFlags_NoDecoration; + viewport->Flags = flags; } // Create window diff --git a/imgui.h b/imgui.h index 25340073..34b52466 100644 --- a/imgui.h +++ b/imgui.h @@ -886,10 +886,11 @@ enum ImGuiConfigFlags_ // [BETA] Viewports ImGuiConfigFlags_ViewportsEnable = 1 << 10, // Viewport enable flags (require both ImGuiConfigFlags_PlatformHasViewports + ImGuiConfigFlags_RendererHasViewports set by the respective back-ends) - ImGuiConfigFlags_ViewportsNoTaskBarIcons= 1 << 11, // Disable task bars icons for all secondary viewports (will set ImGuiViewportFlags_NoTaskBarIcon on them) + ImGuiConfigFlags_ViewportsNoTaskBarIcon = 1 << 11, // Disable task bars icons for all secondary viewports (will set ImGuiViewportFlags_NoTaskBarIcon on them) ImGuiConfigFlags_ViewportsNoMerge = 1 << 12, // All floating windows will always create their own viewport and platform window. - ImGuiConfigFlags_DpiEnableScaleViewports= 1 << 13, // FIXME-DPI: Reposition and resize imgui windows when the DpiScale of a viewport changed (mostly useful for the main viewport hosting other window). Note that resizing the main window itself is up to your application. - ImGuiConfigFlags_DpiEnableScaleFonts = 1 << 14, // FIXME-DPI: Request bitmap-scaled fonts to match DpiScale. This is a very low-quality workaround. The correct way to handle DPI is _currently_ to replace the atlas and/or fonts in the Platform_OnChangedViewport callback, but this is all early work in progress. + ImGuiConfigFlags_ViewportsDecoration = 1 << 13, // FIXME [Broken] Enable platform decoration for all secondary viewports (will not set ImGuiViewportFlags_NoDecoration on them). This currently doesn't behave well in Windows because 1) By default the new window animation get in the way of our transitions, 2) It enable a minimum window size which tends to breaks resizing. You can workaround the later by setting style.WindowMinSize to a bigger value. + ImGuiConfigFlags_DpiEnableScaleViewports= 1 << 14, // FIXME-DPI: Reposition and resize imgui windows when the DpiScale of a viewport changed (mostly useful for the main viewport hosting other window). Note that resizing the main window itself is up to your application. + ImGuiConfigFlags_DpiEnableScaleFonts = 1 << 15, // FIXME-DPI: Request bitmap-scaled fonts to match DpiScale. This is a very low-quality workaround. The correct way to handle DPI is _currently_ to replace the atlas and/or fonts in the Platform_OnChangedViewport callback, but this is all early work in progress. // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. @@ -2068,7 +2069,8 @@ struct ImGuiPlatformIO // Flags stored in ImGuiViewport::Flags, giving indications to the platform back-ends enum ImGuiViewportFlags_ { - ImGuiViewportFlags_NoDecoration = 1 << 0, // Platform Window: Disable platform title bar, borders, etc. + ImGuiViewportFlags_None = 0, + ImGuiViewportFlags_NoDecoration = 1 << 0, // Platform Window: Disable platform decorations: title bar, borders, etc. ImGuiViewportFlags_NoFocusOnAppearing = 1 << 1, // Platform Window: Don't take focus when created. ImGuiViewportFlags_NoInputs = 1 << 2, // Platform Window: Make mouse pass through so we can drag this window while peaking behind it. ImGuiViewportFlags_NoTaskBarIcon = 1 << 3, // Platform Window: Disable platform task bar icon (for popups, menus, or all windows if ImGuiConfigFlags_ViewportsNoTaskBarIcons if set) @@ -2088,9 +2090,9 @@ struct ImGuiViewport void* PlatformUserData; // void* to hold custom data structure for the platform (e.g. windowing info, render context) void* PlatformHandle; // void* for FindViewportByPlatformHandle(). (e.g. suggested to use natural platform handle such as HWND, GlfwWindow*, SDL_Window*) - bool PlatformRequestClose; // Platform window requested closure - bool PlatformRequestMove; // Platform window requested move (e.g. window was moved by the OS / host window manager) - bool PlatformRequestResize; // Platform window requested resize (e.g. window was resize by the OS / host window manager) + bool PlatformRequestClose; // Platform window requested closure (e.g. window was moved by the OS / host window manager, e.g. pressing ALT-F4) + bool PlatformRequestMove; // Platform window requested move (e.g. window was moved by the OS / host window manager, authoritative position will be OS window position) + bool PlatformRequestResize; // Platform window requested resize (e.g. window was resized by the OS / host window manager, authoritative size will be OS window size) void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. swap chain, frame-buffers etc.) ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; RendererUserData = NULL; } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ad343e63..c6d32870 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -312,8 +312,10 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility."); ImGui::CheckboxFlags("io.ConfigFlags: ViewportsEnable", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_ViewportsEnable); ImGui::SameLine(); ShowHelpMarker("Toggling this at runtime is normally unsupported (it will offset your windows)."); - ImGui::CheckboxFlags("io.ConfigFlags: ViewportsNoTaskBarIcons", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_ViewportsNoTaskBarIcons); + ImGui::CheckboxFlags("io.ConfigFlags: ViewportsNoTaskBarIcon", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_ViewportsNoTaskBarIcon); ImGui::SameLine(); ShowHelpMarker("Toggling this at runtime is normally unsupported (most platform back-ends won't refresh the task bar icon state right away)."); + ImGui::CheckboxFlags("io.ConfigFlags: ViewportsDecoration", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_ViewportsDecoration); + ImGui::SameLine(); ShowHelpMarker("Toggling this at runtime is normally unsupported (most platform back-ends won't refresh the decoration right away)."); ImGui::CheckboxFlags("io.ConfigFlags: ViewportsNoMerge", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_ViewportsNoMerge); ImGui::SameLine(); ShowHelpMarker("All floating windows will always create their own viewport and platform window."); ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink); From 15ec78e9d8347ff3e731375181b225e0a5e9318d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Oct 2018 21:31:42 +0200 Subject: [PATCH 2/2] Internal: Moved stored window name update code to the first_begin_of_the_frame block. This will be useful in the Docking branch. --- imgui.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0dfe9795..2b6ef904 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4766,15 +4766,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window = CreateNewWindow(name, size_on_first_use, flags); } - // Update stored window name when it changes (which can only happen with the "###" operator). - // Only if it is meant to be displayed to the end user in a different place than the title bar (which already always display the 'name' parameter) - bool window_title_visible_elsewhere = (window->Viewport && window->Viewport->Window == window); - if (!window_just_created && window_title_visible_elsewhere && strcmp(name, window->Name) != 0) - { - IM_DELETE(window->Name); - window->Name = ImStrdup(name); - } - // Automatically disable manual moving/resizing when NoInputs is set if (flags & ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; @@ -4886,6 +4877,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->LastFrameActive = current_frame; window->IDStack.resize(1); + // Update stored window name when it changes (which can only happen with the "###" operator). + // The title bar always display the 'name' parameter, so we only update storage if the title is displayed to the end-user in a different place. + bool window_title_visible_elsewhere = (window->Viewport && window->Viewport->Window == window); + if (!window_just_created && window_title_visible_elsewhere && strcmp(name, window->Name) != 0) + { + IM_DELETE(window->Name); + window->Name = ImStrdup(name); + } + // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS // Update contents size from last frame for auto-fitting (or use explicit size)