Backends: SDL2, SDL3: macOS: fixed stuck down keys/buttons when they were held in a viewport that gets destroyed. (#9121, #7853)

Regression in 1.91.1 caused by #7853
This commit is contained in:
ocornut 2026-11-05 19:06:37 +01:00
parent 1f3ee75ee4
commit 5c7c293a66
3 changed files with 23 additions and 5 deletions

View File

@ -26,6 +26,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-11-05: [Docking] macOS: fixed stuck down keys/buttons when they were held while the focused viewport gets destroyed. (#9121, #7853)
// 2026-08-06: Fixed querying framebuffer scale when using Metal. (#5592) // 2026-08-06: Fixed querying framebuffer scale when using Metal. (#5592)
// 2026-07-15: Inputs: restore SDL_StartTextInput()/SDL_StopTextInput() in IME handler for on-screen keyboard support on Android/mobile. (#7636, #9474) // 2026-07-15: Inputs: restore SDL_StartTextInput()/SDL_StopTextInput() in IME handler for on-screen keyboard support on Android/mobile. (#7636, #9474)
// 2026-04-16: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value and this breaks scaling border size. (#9369) // 2026-04-16: Made ImGui_ImplSDL2_GetContentScaleForWindow(), ImGui_ImplSDL2_GetContentScaleForDisplay() helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value and this breaks scaling border size. (#9369)
@ -179,6 +180,7 @@ struct ImGui_ImplSDL2_Data
bool IsWayland; bool IsWayland;
bool IsVulkan; bool IsVulkan;
bool WantUpdateMonitors; bool WantUpdateMonitors;
ImVector<Uint32> LastFrameDestroyedWindowIDs;
// Mouse handling // Mouse handling
Uint32 MouseWindowID; Uint32 MouseWindowID;
@ -468,7 +470,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
{ {
if (ImGui_ImplSDL2_GetViewportForWindowID(event->button.windowID) == nullptr) ImGuiViewport* viewport = ImGui_ImplSDL2_GetViewportForWindowID(event->button.windowID);
if (viewport == nullptr && bd->LastFrameDestroyedWindowIDs.contains(event->key.windowID) == false)
return false; return false;
int mouse_button = -1; int mouse_button = -1;
if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
@ -494,7 +497,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
case SDL_KEYUP: case SDL_KEYUP:
{ {
ImGuiViewport* viewport = ImGui_ImplSDL2_GetViewportForWindowID(event->key.windowID); ImGuiViewport* viewport = ImGui_ImplSDL2_GetViewportForWindowID(event->key.windowID);
if (viewport == nullptr) if (viewport == nullptr && bd->LastFrameDestroyedWindowIDs.contains(event->key.windowID) == false)
return false; return false;
//IMGUI_DEBUG_LOG("SDL_KEY%s : key=0x%08X ('%s'), scancode=%d ('%s'), mod=%X, windowID=%d, viewport=%08X\n", //IMGUI_DEBUG_LOG("SDL_KEY%s : key=0x%08X ('%s'), scancode=%d ('%s'), mod=%X, windowID=%d, viewport=%08X\n",
// (event->type == SDL_KEYDOWN) ? "DOWN" : "UP ", event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym), event->key.keysym.scancode, SDL_GetScancodeName(event->key.keysym.scancode), event->key.keysym.mod, event->key.windowID, viewport ? viewport->ID : 0); // (event->type == SDL_KEYDOWN) ? "DOWN" : "UP ", event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym), event->key.keysym.scancode, SDL_GetScancodeName(event->key.keysym.scancode), event->key.keysym.mod, event->key.windowID, viewport ? viewport->ID : 0);
@ -1100,6 +1103,8 @@ void ImGui_ImplSDL2_NewFrame()
// Update game controllers (if enabled and available) // Update game controllers (if enabled and available)
ImGui_ImplSDL2_UpdateGamepads(); ImGui_ImplSDL2_UpdateGamepads();
bd->LastFrameDestroyedWindowIDs.resize(0);
} }
//-------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------
@ -1153,6 +1158,7 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0;
#endif #endif
vd->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Pos.x, (int)viewport->Pos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); vd->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Pos.x, (int)viewport->Pos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags);
vd->WindowID = SDL_GetWindowID(vd->Window);
vd->WindowOwned = true; vd->WindowOwned = true;
if (use_opengl) if (use_opengl)
{ {
@ -1162,7 +1168,7 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
if (use_opengl && backup_context) if (use_opengl && backup_context)
SDL_GL_MakeCurrent(vd->Window, backup_context); SDL_GL_MakeCurrent(vd->Window, backup_context);
viewport->PlatformHandle = (void*)(intptr_t)SDL_GetWindowID(vd->Window); viewport->PlatformHandle = (void*)(intptr_t)vd->WindowID;
viewport->PlatformHandleRaw = nullptr; viewport->PlatformHandleRaw = nullptr;
SDL_SysWMinfo info; SDL_SysWMinfo info;
SDL_VERSION(&info.version); SDL_VERSION(&info.version);
@ -1180,6 +1186,8 @@ static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport)
{ {
if (ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData) if (ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData)
{ {
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
bd->LastFrameDestroyedWindowIDs.push_back(vd->WindowID);
if (vd->GLContext && vd->WindowOwned) if (vd->GLContext && vd->WindowOwned)
SDL_GL_DeleteContext(vd->GLContext); SDL_GL_DeleteContext(vd->GLContext);
if (vd->Window && vd->WindowOwned) if (vd->Window && vd->WindowOwned)

View File

@ -24,6 +24,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-11-05: [Docking] macOS: fixed stuck down keys/buttons when they were held while the focused viewport gets destroyed. (#9121, #7853)
// 2026-03-25: [Docking] Use SDL_HAS_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED (SDL 3.4.0+) when available to avoid refreshing monitor work area every frame on Windows. (#8415) // 2026-03-25: [Docking] Use SDL_HAS_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED (SDL 3.4.0+) when available to avoid refreshing monitor work area every frame on Windows. (#8415)
// 2026-03-09: [Docking] Fixed an issue dated 2025/04/09 (1.92 WIP) where a refactor+merge caused ImGuiBackendFlags_HasMouseHoveredViewport to never be set, causing foreign windows to be ignored when deciding of hovered viewport. (#9284) // 2026-03-09: [Docking] Fixed an issue dated 2025/04/09 (1.92 WIP) where a refactor+merge caused ImGuiBackendFlags_HasMouseHoveredViewport to never be set, causing foreign windows to be ignored when deciding of hovered viewport. (#9284)
// 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL3_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235) // 2026-02-13: Inputs: systems other than X11 are back to starting mouse capture on mouse down (reverts 2025-02-26 change). Only X11 requires waiting for a drag by default (not ideal, but a better default for X11 users). Added ImGui_ImplSDL3_SetMouseCaptureMode() for X11 debugger users. (#3650, #6410, #9235)
@ -128,6 +129,7 @@ struct ImGui_ImplSDL3_Data
bool IsWayland; bool IsWayland;
bool IsVulkan; bool IsVulkan;
bool WantUpdateMonitors; bool WantUpdateMonitors;
ImVector<SDL_WindowID> LastFrameDestroyedWindowIDs;
// IME handling // IME handling
SDL_Window* ImeWindow; SDL_Window* ImeWindow;
@ -437,7 +439,8 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP: case SDL_EVENT_MOUSE_BUTTON_UP:
{ {
if (ImGui_ImplSDL3_GetViewportForWindowID(event->button.windowID) == nullptr) ImGuiViewport* viewport = ImGui_ImplSDL3_GetViewportForWindowID(event->button.windowID);
if (viewport == nullptr && bd->LastFrameDestroyedWindowIDs.contains(event->button.windowID) == false)
return false; return false;
int mouse_button = -1; int mouse_button = -1;
if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
@ -463,7 +466,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
case SDL_EVENT_KEY_UP: case SDL_EVENT_KEY_UP:
{ {
ImGuiViewport* viewport = ImGui_ImplSDL3_GetViewportForWindowID(event->key.windowID); ImGuiViewport* viewport = ImGui_ImplSDL3_GetViewportForWindowID(event->key.windowID);
if (viewport == nullptr) if (viewport == nullptr && bd->LastFrameDestroyedWindowIDs.contains(event->key.windowID) == false)
return false; return false;
//IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%s : key=0x%08X ('%s'), scancode=%d ('%s'), mod=%X, windowID=%d, viewport=%08X\n", //IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%s : key=0x%08X ('%s'), scancode=%d ('%s'), mod=%X, windowID=%d, viewport=%08X\n",
// (event->type == SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP ", event->key.key, SDL_GetKeyName(event->key.key), event->key.scancode, SDL_GetScancodeName(event->key.scancode), event->key.mod, event->key.windowID, viewport ? viewport->ID : 0); // (event->type == SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP ", event->key.key, SDL_GetKeyName(event->key.key), event->key.scancode, SDL_GetScancodeName(event->key.scancode), event->key.mod, event->key.windowID, viewport ? viewport->ID : 0);
@ -1040,6 +1043,8 @@ void ImGui_ImplSDL3_NewFrame()
// Update game controllers (if enabled and available) // Update game controllers (if enabled and available)
ImGui_ImplSDL3_UpdateGamepads(); ImGui_ImplSDL3_UpdateGamepads();
bd->LastFrameDestroyedWindowIDs.resize(0);
} }
//-------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------
@ -1101,6 +1106,7 @@ static void ImGui_ImplSDL3_CreateWindow(ImGuiViewport* viewport)
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon) ? SDL_WINDOW_UTILITY : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoTaskBarIcon) ? SDL_WINDOW_UTILITY : 0;
sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0;
vd->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); vd->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags);
vd->WindowID = SDL_GetWindowID(vd->Window);
#ifndef __APPLE__ // On Mac, SDL3 Parenting appears to prevent viewport from appearing in another monitor #ifndef __APPLE__ // On Mac, SDL3 Parenting appears to prevent viewport from appearing in another monitor
SDL_SetWindowParent(vd->Window, vd->ParentWindow); SDL_SetWindowParent(vd->Window, vd->ParentWindow);
#endif #endif
@ -1121,6 +1127,8 @@ static void ImGui_ImplSDL3_DestroyWindow(ImGuiViewport* viewport)
{ {
if (ImGui_ImplSDL3_ViewportData* vd = (ImGui_ImplSDL3_ViewportData*)viewport->PlatformUserData) if (ImGui_ImplSDL3_ViewportData* vd = (ImGui_ImplSDL3_ViewportData*)viewport->PlatformUserData)
{ {
ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
bd->LastFrameDestroyedWindowIDs.push_back(vd->WindowID);
if (vd->GLContext && vd->WindowOwned) if (vd->GLContext && vd->WindowOwned)
SDL_GL_DestroyContext(vd->GLContext); SDL_GL_DestroyContext(vd->GLContext);
if (vd->Window && vd->WindowOwned) if (vd->Window && vd->WindowOwned)

View File

@ -111,6 +111,8 @@ Docking+Viewports Branch:
- Fixed an issue where in some code paths, a newly created modal in its own - Fixed an issue where in some code paths, a newly created modal in its own
viewport would be created with `ImGuiViewportFlags_NoFocusOnAppearing`. viewport would be created with `ImGuiViewportFlags_NoFocusOnAppearing`.
- Backends: - Backends:
- SDL2, SDL3: on macOS: fixed stuck down keys/buttons when they were held while thee
focused viewport gets destroyed (Regression on macOS in 1.91.1) (#9121, #7853)
- Win32: make windows appear with `::SetWindowPos()` w/ `SWP_NOOWNERZORDER` instead - Win32: make windows appear with `::SetWindowPos()` w/ `SWP_NOOWNERZORDER` instead
of unparenting + `ShowWindow()`. Fixes missing taskbar icon for newly appearing of unparenting + `ShowWindow()`. Fixes missing taskbar icon for newly appearing
windows that are parented and use `ImGuiViewportFlags_NoFocusOnAppearing`. (#7354, #8669) windows that are parented and use `ImGuiViewportFlags_NoFocusOnAppearing`. (#7354, #8669)