imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Need advice for dealing with "global mouse" stuff being unreliable with SDL2

Open alien-brother opened this issue 1 year ago • 2 comments

Version/Branch of Dear ImGui:

Version 1.91,5 Branch: master

Back-ends:

imgui_impl_sdl2.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Linux, GCC 14, SDL 2.30.9

Full config/build information:

Dear ImGui 1.91.5 (19150)
--------------------------------

sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=202002
define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS
define: __linux__
define: __GNUC__=14
--------------------------------

io.BackendPlatformName: imgui_impl_sdl2
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000001
 NavEnableKeyboard
io.ConfigNavCaptureKeyboard
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x0000000E
 HasMouseCursors
 HasSetMousePos
 RendererHasVtxOffset
--------------------------------

io.Fonts: 4 fonts, Flags: 0x00000000, TexSize: 512,128
io.DisplaySize: 956.00,509.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------

style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 5.00,3.00
style.FrameRounding: 3.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 6.00,6.00
style.ItemInnerSpacing: 3.00,3.00

Details:

My Issue/Question:

I'm trying to use ImGui in a child window of an existing X11 window. The "host" code gives me the parent window, I create a new window with SDL2 and call XReparentWindow(). The side effect of this is that the result of SDL_GetWindowPosition() seems to no longer be valid (I assume a child window does not receive the messages required for updating position) and this causes this function to generate mouse events with incorrect position:

static void ImGui_ImplSDL2_UpdateMouseData()
{
    ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
    ImGuiIO& io = ImGui::GetIO();

    // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below)
#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
    // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
    SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE);
    SDL_Window* focused_window = SDL_GetKeyboardFocus();
    const bool is_app_focused = (bd->Window == focused_window);
#else
    const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only
#endif
    if (is_app_focused)
    {
        // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
        if (io.WantSetMousePos)
            SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);

        // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured)
        if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0)
        {
            int window_x, window_y, mouse_x_global, mouse_y_global;
            SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
            SDL_GetWindowPosition(bd->Window, &window_x, &window_y);
            io.AddMousePosEvent((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
        }
    }
}
  • What would be the right workaround? Naively, I'd just want to set bd->MouseCanUseGlobalState to false and let the mouse motion events track the mouse pointer. Can I do it without patching ImGui source code?
  • Or maybe there is a way to fix window position stuff after reparenting?

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

No response

alien-brother avatar Nov 28 '24 05:11 alien-brother

Note that f61a7ef22 (Sept 2025) has reduced the scope of using SDL_GetGlobalMouseState() to situation where your application window is NOT hovered only. So it should largely mitigate the issue.

I don't quite understand your child/reparenting thing (please post a video with Debug Log->IO values visible) but there is a possibility that updating to latest would fix the issue.

ocornut avatar Nov 24 '25 16:11 ocornut

Thanks for looking into it.

I haven't touched this topic for a while; I'll try to see what changes with the update. Looking at the diff I would think it indeed fixes most issues.

The original issue is that after reparenting, the return value of SDL_GetWindowPosition() is wrong.

alien-brother avatar Nov 25 '25 23:11 alien-brother