Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting window size to a non-integer value can make the window move by itself #2067

Closed
ldecarufel opened this issue Sep 7, 2018 · 2 comments
Labels

Comments

@ldecarufel
Copy link

Calling ImGui::SetWindowSize() with a size that hasn't been rounded to an integer value can make the window move by itself due to rounding errors inside ImGui::Begin().

Let's consider the following call:
ImGui::SetWindowSize(ImVec2(348.48f, 400.0f));

This will set the value of "window->SizeFull.x" to "348.480011" in the SetWindowSize() function (the values were taken from the debugger).

On the next call to ImGui::Begin(), when the window position is clamped to the visible area, a rounding error can make the window position change (see my comments in the code):

// Clamp position so it stays visible
if (!(flags & ImGuiWindowFlags_ChildWindow))
{
    if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
    {
        ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
        // Here window->Pos.x == 170.000000 and window->Size.x == 348.480011
        window->Pos = ImMax(window->Pos + window->Size, padding) - window->Size;
        // Here window->Pos.x == 169.999969 due to rounding error
        window->Pos = ImMin(window->Pos, g.IO.DisplaySize - padding);
    }
}

window->Pos = ImFloor(window->Pos);
// And finally, here window->Pos.x has become 169.000000

The solution would be to round the window size in the ImGui::SetWindowSize() function.

Of course, I changed the code on our side to make sure the size was always rounded before calling ImGui::SetWindowSize(), but it would be safer to round the size in the ImGui function to avoid weird behavior.

ocornut added a commit that referenced this issue Sep 7, 2018
…lues leading to accidental alteration of window position. We now round the provided size. (#2067)
@ocornut
Copy link
Owner

ocornut commented Sep 7, 2018

Thank you Louis. Should be fixed now!

@ocornut ocornut closed this as completed Sep 7, 2018
@ocornut ocornut added the bug label Sep 7, 2018
@przemkovv
Copy link

I found that the same issue appears when SizeConstraintRect has non rounded values. In that case, the CalcSizeAfterConstraint function returns a new, non-rounded size which is then used by a code fragment quoted by OP.

// g.NextWindowData.SizeConstraintRect = {Min={x=475.200012 y=0.000000000 } Max={x=475.200012 y=688.799988 } }
// new_size = {x=475.000000 y=491.000000 }

ImRect cr = g.NextWindowData.SizeConstraintRect;
new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;

// new_size = {x=475.200012 y=491.000000 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants