diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index 9384cecee414..47cb6a140472 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -96,6 +96,7 @@ struct ImGui_ImplSDL2_Data Uint32 MouseWindowID; int MouseButtonsDown; SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT]; + int PendingMouseLeaveFrame; char* ClipboardTextData; bool MouseCanUseGlobalState; bool UseVulkan; @@ -315,16 +316,19 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_WINDOWEVENT: { - // When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. - // However we won't get a correct LEAVE event for a captured window. + // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. + // - However we won't get a correct LEAVE event for a captured window. + // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, + // causing SDL_WINDOWEVENT_LEAVE on previous frame to interrupt drag operation by clear mouse position. This is why + // we delay process the SDL_WINDOWEVENT_LEAVE events by one frame. See issue #5012 for details. Uint8 window_event = event->window.event; if (window_event == SDL_WINDOWEVENT_ENTER) - bd->MouseWindowID = event->window.windowID; - if (window_event == SDL_WINDOWEVENT_LEAVE) { - bd->MouseWindowID = 0; - io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + bd->MouseWindowID = event->window.windowID; + bd->PendingMouseLeaveFrame = 0; } + if (window_event == SDL_WINDOWEVENT_LEAVE) + bd->PendingMouseLeaveFrame = ImGui::GetFrameCount() + 1; if (window_event == SDL_WINDOWEVENT_FOCUS_GAINED) io.AddFocusEvent(true); else if (window_event == SDL_WINDOWEVENT_FOCUS_LOST) @@ -665,6 +669,12 @@ void ImGui_ImplSDL2_NewFrame() io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f); bd->Time = current_time; + if (bd->PendingMouseLeaveFrame && bd->PendingMouseLeaveFrame == ImGui::GetFrameCount()) + { + bd->MouseWindowID = 0; + io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); + } + ImGui_ImplSDL2_UpdateMouseData(); ImGui_ImplSDL2_UpdateMouseCursor(); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6186bbcb71c5..d730d7a7254d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -134,6 +134,7 @@ Docking+Viewports Branch: - Docking: Fixed floating docked nodes not being clamped into viewport workrect to stay reachable when g.ConfigWindowsMoveFromTitleBarOnly is set and multi-viewports are disabled. (#5044) +- Backends: SDL: Fixed dragging out main viewport broken on some SDL setups. (#5012) [@rokups] - Viewports: Fixed translating a host viewport from briefly altering the size of AlwaysAutoResize windows. (#5057) - Viewports: Fixed main viewport size not matching ImDrawData::DisplaySize for one frame during resize when multi-viewports are disabled. (#4900)