diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 308fb12b..6a39d143 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -135,6 +135,7 @@ int main(int, char**) ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; //io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons; + //io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge; io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleFonts; io.ConfigFlags |= ImGuiConfigFlags_DpiEnableScaleViewports; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 7cc6e5ae..0da56b63 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -518,6 +518,22 @@ static float ImGui_ImplWin32_GetWindowDpiScale(ImGuiViewport* viewport) (int)(viewport->Pos.x + viewport->Size.x), (int)(viewport->Pos.y + viewport->Size.y)); } +// FIXME-DPI: Testing DPI related ideas +static void ImGui_ImplWin32_OnChangedViewport(ImGuiViewport* viewport) +{ + (void)viewport; +#if 0 + ImGuiStyle default_style; + //default_style.WindowPadding = ImVec2(0, 0); + //default_style.WindowBorderSize = 0.0f; + //default_style.ItemSpacing.y = 3.0f; + //default_style.FramePadding = ImVec2(0, 0); + default_style.ScaleAllSizes(viewport->DpiScale); + ImGuiStyle& style = ImGui::GetStyle(); + style = default_style; +#endif +} + static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) @@ -604,6 +620,7 @@ static void ImGui_ImplWin32_InitPlatformInterface() platform_io.Platform_SetWindowTitle = ImGui_ImplWin32_SetWindowTitle; platform_io.Platform_SetWindowAlpha = ImGui_ImplWin32_SetWindowAlpha; platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; + platform_io.Platform_OnChangedViewport = ImGui_ImplWin32_OnChangedViewport; // FIXME-DPI // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); diff --git a/imgui.cpp b/imgui.cpp index 3ab3dd67..d423d425 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -752,7 +752,7 @@ static void NavUpdate(); static void NavUpdateWindowing(); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id); -static void NewFrameUpdateMovingWindow(); +static void UpdateMovingWindow(); static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); @@ -3305,6 +3305,16 @@ static void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport) window->ViewportOwned = (viewport->Window == window); } +static bool GetWindowAlwaysWantOwnViewport(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) && (g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoMerge)) + //if (window->DockStatus == ImGuiDockStatus_Floating) + if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_ChildMenu)) == 0) + return true; + return false; +} + static void ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport) { ImGuiContext& g = *GImGui; @@ -3314,6 +3324,8 @@ static void ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImG return; if (!viewport->GetRect().Contains(window->Rect())) return; + if (GetWindowAlwaysWantOwnViewport(window)) + return; // Move to the existing viewport, Move child/hosted windows as well (FIXME-OPT: iterate child) ImGuiViewportP* old_viewport = window->Viewport; @@ -3324,7 +3336,7 @@ static void ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImG SetWindowViewport(window, viewport); } -static void ImGui::NewFrameUpdateMovingWindow() +static void ImGui::UpdateMovingWindow() { ImGuiContext& g = *GImGui; if (g.MovingWindow && g.MovingWindow->MoveId == g.ActiveId && g.ActiveIdSource == ImGuiInputSource_Mouse) @@ -3474,9 +3486,11 @@ static void ImGui::UpdateViewports() //if (viewport == GetMainViewport()) // g.PlatformInterface.SetWindowSize(viewport, viewport->Size * scale_factor); - // FIXME-DPI: We need to preserve our pivots - //if (g.MovingWindow) - // g.ActiveIdClickOffset = g.ActiveIdClickOffset * scale_factor; + // Scale our window moving pivot so that the window will rescale roughly around the mouse position. + // FIXME-VIEWPORT: This currently creates a resizing feedback loop when a window is straddling a DPI transition border. + // (Minor: since our sizes do not perfectly linearly scale, deferring the click offset scale until we know the actual window scale ratio may get us slightly more precise mouse positioning.) + //if (g.MovingWindow != NULL && g.MovingWindow->Viewport == viewport) + // g.ActiveIdClickOffset = ImFloor(g.ActiveIdClickOffset * scale_factor); } viewport->DpiScale = new_dpi_scale; } @@ -3897,7 +3911,7 @@ void ImGui::NewFrame() g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX; // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) - NewFrameUpdateMovingWindow(); + UpdateMovingWindow(); NewFrameUpdateHoveredWindowAndCaptureFlags(); if (GetFrontMostPopupModal() != NULL) @@ -6184,6 +6198,10 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) window->Viewport = AddUpdateViewport(window, window->ID, viewport_flags, viewport_pos, window->Size); } } + else if (!window->ViewportOwned && GetWindowAlwaysWantOwnViewport(window)) + { + window->Viewport = AddUpdateViewport(window, window->ID, ImGuiViewportFlags_NoDecoration, window->Pos, window->Size); + } // Mark window as allowed to protrude outside of its viewport and into the current monitor bool allow_protrude_on_whole_monitor = false; @@ -14010,20 +14028,6 @@ static void ScaleWindow(ImGuiWindow* window, float scale) void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale) { ImGuiContext& g = *GImGui; - - // FIXME-DPI: This is meant to have the window rescale around the mouse. It currently creates feedback loop when a window is straddling a DPI transition border. - // NB: since our sizes do not perfectly linearly scale, deferring the ClickOffset scale until we know the actual window scale ratio may get us slightly more precise mouse positioning. - //if (g.MovingWindow != NULL && g.MovingWindow->Viewport == viewport) - // g.ActiveIdClickOffset = ImFloor(g.ActiveIdClickOffset * scale); - - /* - if (g.IO.MousePosViewport == viewport->ID) - { - g.IO.MousePos = g.IO.MousePosPrev = ImFloor((g.IO.MousePos - viewport->Pos) * scale) + viewport->Pos; - g.IO.MouseDelta = ImVec2(0,0); - } - */ - if (viewport->Window) { ScaleWindow(viewport->Window, scale); @@ -14036,7 +14040,6 @@ void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale) } } - static void RenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 8c6e5b54..f7e49048 100644 --- a/imgui.h +++ b/imgui.h @@ -787,22 +787,24 @@ enum ImGuiNavInput_ // Configuration flags stored in io.ConfigFlags. Set by user/application. enum ImGuiConfigFlags_ { - ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeysDown[]. - ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad. - ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. - ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag with io.NavActive is set. - ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information back-end - ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct back-end to not alter mouse cursor shape and visibility. + ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeysDown[]. + ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad. + ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag with io.NavActive is set. + ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information back-end + ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct back-end to not alter mouse cursor shape and visibility. // [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_DpiEnableScaleViewports = 1 << 12, - ImGuiConfigFlags_DpiEnableScaleFonts = 1 << 13, + ImGuiConfigFlags_ViewportsNoMerge = 1 << 12, // All floating windows _always_ have create their own viewport and platform window. + + ImGuiConfigFlags_DpiEnableScaleViewports = 1 << 13, + ImGuiConfigFlags_DpiEnableScaleFonts = 1 << 14, // 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. - ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Application is using a touch screen instead of a mouse. + ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. + ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Application is using a touch screen instead of a mouse. }; // Back-end capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom back-end.