Version/Branch of Dear ImGui:
Version 1.92.8 WIP, Branch: docking
Back-ends:
imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp
Compiler, OS:
Linux Ubuntu 22.04, GCC 11.4.0, X11/GNOME Shell, kernel 6.8.0
Full config/build information:
ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable
Details:
My Issue / Question:
When a window is undocked into a secondary viewport (a separate OS window), it cannot be dragged beyond the monitor edge — it hits an invisible wall — even though the main GLFW window and other native apps (e.g. VSCode) can freely cross that boundary.
Additionally, while the secondary viewport is at or near the monitor edge, the rendered content (e.g. a crosshair drawn at mouse coordinates) appears visually offset from the actual cursor position.
Root cause (traced in source):
-
Monitor-edge wall —
ClampWindowPosinimgui.cpp(around thewindow->ViewportOwnedbranch, ~line 8257–8272) limits the window position tomonitor->WorkPos + monitor->WorkSizeexpanded by-visibility_padding(defaultDisplayWindowPadding = {19, 19}). ThePlatformMonitorsFullWorkRectpath that allows straddling (#7299, #3071) is only entered wheng.MovingWindow != NULL && window->RootWindowDockTree == g.MovingWindow->RootWindowDockTree. During a viewport-owned drag this condition is met, butvisibility_rectis then expanded by-visibility_paddingwhich still applies 19 px of clamping — the window can get close to the edge but not past it. -
Content shift —
NewFrame()setsviewport->Posto the desired position (cursor − grab delta, which may be beyond the monitor edge).TranslateWindowsInViewporthas already shifted imgui child windows toLastPlatformPos(the actual OS position, clamped by the WM). So afterNewFrame():- ImGui child-window global coordinates are based on
P_actual viewport->Pos(==DisplayPos) equalsP_desired- Result: every pixel in the viewport is rendered with a
P_actual − P_desiredoffset → crosshair and mouse-position overlays appear shifted by the "overshoot" amount.
- ImGui child-window global coordinates are based on
Expected behavior:
Secondary viewports should be draggable beyond the monitor edge the same way the main window is (the OS/WM ultimately controls whether the window actually moves). Rendered content should never appear shifted relative to the cursor while dragging near a monitor boundary.
Steps to reproduce:
- Enable
ImGuiConfigFlags_ViewportsEnable. - Undock any window so it becomes a secondary OS window.
- Drag the secondary window toward and past the monitor edge.
→ Window stops at ~19 px from the edge (the
DisplayWindowPaddinglimit). - While it is stopped at the edge, content rendered at
io.MousePos(e.g. a crosshair) appears shifted by the amount the drag "wanted" to move the window further.
Screenshots/Video:
No response
Minimal, Complete and Verifiable Example code:
// Standard docking+viewports example (Dear ImGui demo is sufficient to reproduce). // 1. Run imgui_demo with viewports enabled on Linux/X11. // 2. Undock "Dear ImGui Demo" window (drag it out of the main window). // 3. Draw a crosshair at io.MousePos inside the secondary window's Begin/End. // 4. Drag the secondary window to a monitor edge. // Observe: window stops moving before the edge; crosshair shifts from cursor.
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Once); ImGui::Begin("Viewport test"); ImVec2 p = ImGui::GetMousePos(); ImGui::GetForegroundDrawList()->AddLine({p.x - 10, p.y}, {p.x + 10, p.y}, IM_COL32(255, 0, 0, 255)); ImGui::GetForegroundDrawList()->AddLine({p.x, p.y - 10}, {p.x, p.y + 10}, IM_COL32(255, 0, 0, 255)); ImGui::End();
Activity
0No activity yet.