From 227ed82c6c3ddd7af27239c9f1536c0cd7ad4e84 Mon Sep 17 00:00:00 2001 From: The Loki Date: Sun, 30 Jun 2024 14:30:33 +0800 Subject: [PATCH] Fix rendering errors caused by dragging the window across monitors with different DPI scaling. --- backends/imgui_impl_glfw.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 23b0adb8b..d401d3b74 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -190,6 +190,7 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() // Forward Declarations static void ImGui_ImplGlfw_UpdateMonitors(); +static void ImGui_ImplGlfw_UpdateViewports(); static void ImGui_ImplGlfw_InitPlatformInterface(); static void ImGui_ImplGlfw_ShutdownPlatformInterface(); @@ -924,6 +925,7 @@ void ImGui_ImplGlfw_NewFrame() io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); bd->Time = current_time; + ImGui_ImplGlfw_UpdateViewports(); ImGui_ImplGlfw_UpdateMouseData(); ImGui_ImplGlfw_UpdateMouseCursor(); @@ -979,6 +981,7 @@ struct ImGui_ImplGlfw_ViewportData { GLFWwindow* Window; bool WindowOwned; + bool PlatformRequestResizeNextFrame; int IgnoreWindowPosEventFrame; int IgnoreWindowSizeEventFrame; #ifdef _WIN32 @@ -989,6 +992,25 @@ struct ImGui_ImplGlfw_ViewportData ~ImGui_ImplGlfw_ViewportData() { IM_ASSERT(Window == nullptr); } }; +static void ImGui_ImplGlfw_UpdateViewports() +{ + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + for (int n = 0; n < platform_io.Viewports.Size; n++) + { + ImGuiViewport* viewport = platform_io.Viewports[n]; + if (ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData){ + if(vd->PlatformRequestResizeNextFrame){ + // The previous frame's windowSizeCallback was invoked when glfwSetWindowPos was used, not triggered by glfwPollEvent. + // At this point, some critical operations that depend on PlatformRequestResize have already been completed. + // The PlatformRequestResize flag is cleared at the end of the frame, + // so we delay the operation to the current frame to ensure that the PlatformRequestResize behavior is fully completed. + viewport->PlatformRequestResize = true; + vd->PlatformRequestResizeNextFrame = false; + } + } + } +} + static void ImGui_ImplGlfw_WindowCloseCallback(GLFWwindow* window) { if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window)) @@ -1026,6 +1048,15 @@ static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int) //data->IgnoreWindowSizeEventFrame = -1; if (ignore_event) return; + + bool delay_to_next_frame = (ImGui::GetFrameCount() <= vd->IgnoreWindowPosEventFrame + 1); + + if(delay_to_next_frame){ + // glfwSetWindowPos and glfwSetWindowSizeCallback are called in the same frame + // we should not process the resize event in this frame + vd->PlatformRequestResizeNextFrame = true; + return; + } } viewport->PlatformRequestResize = true; }