Description
Version/Branch of Dear ImGui:
Version: 1.90 WIP (18992)
Branch: docking
Back-end/Renderer/Compiler/OS
Back-ends: (tested with) example_win32_directx11, example_win32_opengl3, custom backend
Operating System: Windows 10
Issue:
On a setup with multiple monitors, content inside an imgui child window gets clipped on the left side of the clipping rectangle if the viewport/platform window is positioned on a monitor with negative X coordinates.
On Windows, when using multiple monitors, one monitor is always set as the 'main monitor'. Other monitors can then be positioned left, right, above or below. All monitors together use one big coordinate system with the origin being in the top left corner of the main monitor (at least on all my systems/setups). On a setup where there is a monitor left to the main monitor, most coordinates used by Windows will become negative on the x axis. This includes e.g. mouse position or window position.
If we move our window to such a monitor with negative x coordinates, imgui items that are very close to the clipping rectangle border can be cut off as seen here:
The effect is most notable with frame borders enabled (and a high contrast) but to a sharp eye it is also visible on widgets with rounded frames. The text is also affected.
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1);
ImGui::Begin("Hello, world!");
ImGui::BeginChild("Child", ImVec2(0, 0), false);
int v;
ImGui::InputInt("TestInput", &v);
ImGui::Text("Window pos X: %f", ImGui::GetWindowPos().x);
ImGui::EndChild();
ImGui::End();
ImGui::PopStyleVar();
A possible monitor setup is the one below as seen in the Windows 10 desktop settings.
The platform window of the imgui application would have to be on screen one with this setup.
My best guess is that internally the clipping rectangle coordinates get floored which in the worst case usually shifts the left clipping rectangle border <1px to the left. However for negative floats this will shift the left border <1px to the right.
The culprit seems to be the code below (imgui.cpp ImGui::Begin(), Line: 7157) where the clipping rectangle gets floored.
There is probably a smarter way to solve this than adding a check for negative coordinates but I'm not sure.
float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize));
window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size);
window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize));
window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - window->WindowBorderSize);
window->InnerClipRect.ClipWithFull(host_rect);