Skip to content

Race-condition when calculating framebuffer-scale on X11 #8920

@TheBrokenRail

Description

@TheBrokenRail

Version/Branch of Dear ImGui:

master (02af06ea5f57696b93f0dfe77a9e2525522ba76e)

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl2.cpp

Compiler, OS:

Ubuntu 24.10, GNOME XWayland, GCC 14.2.0

Full config/build information:

No response

Details:

My Issue/Question:

ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale divides the framebuffer size by the window size to get the framebuffer scale. To do this, it uses glfwGetWindowSize and glfwGetFramebufferSize. On X11, glfwGetFramebufferSize just calls glfwGetWindowSize (because X11 does not support scaling). glfwGetWindowSize makes a call to XGetWindowAttributes.

It is possible (albeit rare) for the window size to change between these two calls. This will causes a non-1.0 scale to bet set on X11, which should never happen. Most of the time, the scale will momentarily be set to something like (0.725169, 0.745940) before being immediately corrected. But sometimes, it will get set to extremely erroneous values like (1123.000000, 0.894057), causing a crash.

I don't know if this happens on "real" X11, but it definitely happens on GNOME's XWayland implementation.

Steps To Reproduce

  1. Apply the following patch:
    --- a/backends/imgui_impl_glfw.cpp
    +++ b/backends/imgui_impl_glfw.cpp
    @@ -919,6 +919,9 @@ void ImGui_ImplGlfw_NewFrame()
     
         // Setup main viewport size (every frame to accommodate for window resizing)
         ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(bd->Window, &io.DisplaySize, &io.DisplayFramebufferScale);
    +    if (io.DisplayFramebufferScale.x != 1.0f || io.DisplayFramebufferScale.y != 1.0f) {
    +        fprintf(stderr, "Scale: %f %f\n", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
    +    }
     
         // Setup time step
         // (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644)
  2. Run XDG_SESSION_TYPE=x11 ./example_glfw_opengl2 (this will force it to use XWayland/X11).
  3. Start resizing the window like your life depends on it.
  4. Pay attention to the invalid scales being printed to the terminal.

Solution

X11 doesn't support HiDPI, just add a if (glfwGetPlatform() == GLFW_PLATFORM_X11) check and return (1.0, 1.0).

Screenshots/Video:

With V-Sync (The Default)

Screencast.From.2025-09-06.02-31-01.webm.crushed.mp4

Without V-Sync

Screencast.From.2025-09-06.02-44-39.webm.crushed.mp4

Minimal, Complete and Verifiable Example code:

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions