Fix rendering errors caused by dragging the window across monitors with different DPI scaling.

This commit is contained in:
The Loki 2024-06-30 14:30:33 +08:00
parent 3fec562da1
commit 227ed82c6c
1 changed files with 31 additions and 0 deletions

View File

@ -190,6 +190,7 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
// Forward Declarations // Forward Declarations
static void ImGui_ImplGlfw_UpdateMonitors(); static void ImGui_ImplGlfw_UpdateMonitors();
static void ImGui_ImplGlfw_UpdateViewports();
static void ImGui_ImplGlfw_InitPlatformInterface(); static void ImGui_ImplGlfw_InitPlatformInterface();
static void ImGui_ImplGlfw_ShutdownPlatformInterface(); 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); io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
bd->Time = current_time; bd->Time = current_time;
ImGui_ImplGlfw_UpdateViewports();
ImGui_ImplGlfw_UpdateMouseData(); ImGui_ImplGlfw_UpdateMouseData();
ImGui_ImplGlfw_UpdateMouseCursor(); ImGui_ImplGlfw_UpdateMouseCursor();
@ -979,6 +981,7 @@ struct ImGui_ImplGlfw_ViewportData
{ {
GLFWwindow* Window; GLFWwindow* Window;
bool WindowOwned; bool WindowOwned;
bool PlatformRequestResizeNextFrame;
int IgnoreWindowPosEventFrame; int IgnoreWindowPosEventFrame;
int IgnoreWindowSizeEventFrame; int IgnoreWindowSizeEventFrame;
#ifdef _WIN32 #ifdef _WIN32
@ -989,6 +992,25 @@ struct ImGui_ImplGlfw_ViewportData
~ImGui_ImplGlfw_ViewportData() { IM_ASSERT(Window == nullptr); } ~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) static void ImGui_ImplGlfw_WindowCloseCallback(GLFWwindow* window)
{ {
if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window)) if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle(window))
@ -1026,6 +1048,15 @@ static void ImGui_ImplGlfw_WindowSizeCallback(GLFWwindow* window, int, int)
//data->IgnoreWindowSizeEventFrame = -1; //data->IgnoreWindowSizeEventFrame = -1;
if (ignore_event) if (ignore_event)
return; 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; viewport->PlatformRequestResize = true;
} }