Skip to content

GLFW multi-viewport position mismatch when window manager clamps secondary viewport #9442

@KBentley57

Description

@KBentley57

Version/Branch of Dear ImGui:

Version 1.92.8, Branch: docking

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Linux/X11, observed with GLFW + OpenGL3. This is easiest to reproduce with a window manager that clamps programmatic window positions near monitor edges, such as GNOME Shell/Mutter.

I have confirmed the issue across Dear ImGui versions from at least 1.90 through current docking HEAD, using GCC 13 and GCC 14. It has been reproduced on Debian 13, Ubuntu 24.04, Ubuntu under WSL, Red Hat Enterprise Linux 8, Red Hat Enterprise Linux 9, Rocky Linux 8, and Rocky Linux 9.

Full config/build information:

The repro enables:

io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

The detached test window uses ImGuiViewportFlags_NoAutoMerge through ImGuiWindowClass so only that window becomes a secondary platform viewport.

Details:

When a secondary GLFW platform viewport is moved or programmatically requested near a monitor edge, the window manager may clamp the actual platform window position. Dear ImGui may continue to store the requested position in viewport->Pos, while glfwGetWindowPos() reports the actual clamped position.

Once those positions diverge, hit-testing/rendering in the secondary viewport can appear offset from the mouse cursor. Moving the viewport back into the interior of the monitor usually clears the mismatch.

The relevant backend behavior appears to be in ImGui_ImplGlfw_WindowPosCallback(). The backend intentionally ignores window-position callbacks for one frame after glfwSetWindowPos() so it does not process ordinary echo events. That makes sense when GLFW reports the same position Dear ImGui requested. But on X11, the callback may report a different position because the window manager clamped the platform window. Ignoring that callback leaves Dear ImGui synchronized to the requested position instead of the real platform position.

I opened a small PR that keeps the existing ignore behavior for exact echo events, but treats a different reported position as a real platform move:

#9441

Related reports/discussion:

Screenshots/Video:

The repro displays both Dear ImGui's cached viewport position and the actual GLFW platform window position, which makes the mismatch visible numerically.

Normal expected layout: the main controls viewport and detached secondary viewport are both visible, and the secondary viewport reports Delta: (0, 0) / OK.

Normal layout with matching cached and platform positions

Bottom/left edge clamp on the affected backend: the detached viewport is clamped by the window manager, while Dear ImGui still has the requested position cached. The table shows MISMATCH, cached (-61, 1224), platform (0, 1128), delta (61, 96).

Bottom edge mismatch showing cached and platform position delta

Top edge clamp on the affected backend: the same mismatch appears with a smaller top-edge delta, cached (958, -9), platform (959, 0).

Top edge mismatch showing cached and platform position delta

Expected corrected behavior: after synchronizing to the actual platform position, the cached and GLFW platform positions match again and the status returns to OK.

Corrected behavior with matching cached and platform positions

Minimal, Complete and Verifiable Example code:

Minimal repro repository:

https://github.com/KBentley57/imgui-viewport-edge-repro

Build it against an unmodified v1.92.8-docking checkout:

cmake -S . \
      -B /tmp/imgui_viewport_edge_repro_build \
      -DIMGUI_SOURCE_DIR=/path/to/imgui \
      -DCMAKE_PREFIX_PATH=/path/to/glfw/prefix
cmake --build /tmp/imgui_viewport_edge_repro_build -j"$(nproc)"
/tmp/imgui_viewport_edge_repro_build/imgui_viewport_edge_repro

Steps:

  1. Leave Apply platform position sync workaround unchecked.
  2. Click Spawn / reset detached viewport.
  3. Click Request bottom-edge clamp or drag the detached OS window into a monitor edge.
  4. Compare Cached viewport pos with GLFW platform pos.
  5. Build the same repro against the PR branch and repeat.

With the affected backend, the cached and platform positions can diverge near the edge. With the PR branch, the backend should accept the clamped/different callback and converge back to the actual platform position.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions