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

ImGui::GetWindowSize() on tooltip window giving strange sizes #175

Closed
adamdmoss opened this issue Mar 22, 2015 · 12 comments
Closed

ImGui::GetWindowSize() on tooltip window giving strange sizes #175

adamdmoss opened this issue Mar 22, 2015 · 12 comments

Comments

@adamdmoss
Copy link
Contributor

I'm using the following code as wrappers to ImGui::BeginTooltip() and ImGui::EndTooltip() to make sure that tooltips always remain on-screen and unobscured by the mouse cursor.
This worked well until a few revisions ago (probably a change yesterday).

Now ImGui::GetWindowSize() is returning several different sizes for even the simplest single-line-of-text tooltips, causing the tooltip to wobble around. This also occurs when the tooltip isn't near the screen edges, where both X and Y sizes will still appear to vary by several pixels as the cursor is wiggled.

On fairly complex tooltips, the returned sizes can even be negative!

static ImVec2 last_tooltip_size(0.f, 0.f);

void BeginTooltip()
{
    ImGuiIO &io = ImGui::GetIO();
    ImVec2 whole_content_size = io.DisplaySize;
    ImVec2 cursor_pos = io.MousePos;
    ImVec2 tooltip_offset(10.0f, 10.0f);

    ImVec2 tooltip_position = cursor_pos;
    tooltip_position.x += tooltip_offset.x;
    tooltip_position.y += tooltip_offset.y;

    // Keep the tooltip within the content area

    if (tooltip_position.x + last_tooltip_size.x > whole_content_size.x)
    {
        tooltip_position.x = whole_content_size.x - last_tooltip_size.x;
    }

    if (tooltip_position.y + last_tooltip_size.y > whole_content_size.y)
    {
        tooltip_position.y = whole_content_size.y - last_tooltip_size.y;
    }

    // If the adjusted tooltip area now overlaps the
    // cursor position then move it to the left of
    // the cursor.

    if (cursor_pos.x >= tooltip_position.x &&
        cursor_pos.x <= tooltip_position.x + last_tooltip_size.x &&
        cursor_pos.y >= tooltip_position.y &&
        cursor_pos.y <= tooltip_position.y + last_tooltip_size.y)
    {
        tooltip_position.x =
                cursor_pos.x - last_tooltip_size.x
                - tooltip_offset.x;
    }

    ImGui::SetNextWindowPos(tooltip_position);

    ImGui::BeginTooltip();
}


void EndTooltip()
{
    last_tooltip_size = ImGui::GetWindowSize();

    ImGui::EndTooltip();
}
@ocornut
Copy link
Owner

ocornut commented Mar 22, 2015

Well would depend entirely on what's in the actual tooltips. Can you post some code that fails?
I tried with simple line of text and it worked.

(Btw- clamping tooltip within the display area could/should be done by ImGui. I had some code doing that in a local branch, need to decide on the settings.)

@adamdmoss
Copy link
Contributor Author

Fiddling some more, I think this here is probably the root of my woes, though I don't know why the behaviour would have changed recently:

Here's odd example #1:

        ImGui::BeginTooltip();
        ImGui::Text("foo bar baz");
        ImVec2 last_tooltip_size = ImGui::GetWindowSize();
        ImGui::EndTooltip();

        fprintf(stderr, "LTTS: %f x %f\n", last_tooltip_size.x, last_tooltip_size.y);

The first time around this will return a window size of 8x4. Subsequent times around it will return the (probably) correct size of 103x29.

Now a tweaked version, example #2:

        ImGui::SetNextWindowPos(ImVec2(100.0f, 100.0f));
        ImGui::BeginTooltip();
        ImGui::Text("foo bar baz");
        ImVec2 last_tooltip_size = ImGui::GetWindowSize();
        ImGui::EndTooltip();

        fprintf(stderr, "LTTS: %f x %f\n", last_tooltip_size.x, last_tooltip_size.y);

Note the ImGui::SetNextWindowPos(ImVec2(100.0f, 100.0f));.
Now the first time around, the tooltip window size returned will be -92x-96

@adamdmoss
Copy link
Contributor Author

(I agree that ImGui should/could be doing smarter tooltip positioning, I merely figured I could prototype it at the app level and submit it if it became clean enough.)

ocornut added a commit that referenced this issue Mar 22, 2015
Maybe have side-effects on window contents? Unsure at this point.
@ocornut
Copy link
Owner

ocornut commented Mar 22, 2015

Sorry referring to wrong issue number. The commit above is for #176

@adamdmoss
Copy link
Contributor Author

Example #3 - I think the SetNextWindowPos() complicates matters, and this may be a different issue to the issue of the initial dimensions being wrong.

      ImVec2 cursor_pos = ImGui::GetIO().MousePos;
      ImVec2 tooltip_offset(50.0f, 50.0f);

      ImVec2 tooltip_position = cursor_pos;
      tooltip_position.x += tooltip_offset.x;
      tooltip_position.y += tooltip_offset.y;
      ImGui::SetNextWindowPos(tooltip_position);

      ImGui::BeginTooltip();
      ImGui::Text("foo bar baz");
      ImVec2 last_tooltip_size = ImGui::GetWindowSize();
      ImGui::EndTooltip();

      fprintf(stderr, "LTTS: %f x %f\n", last_tooltip_size.x, last_tooltip_size.y);

The result is sometimes 103.000000 x 29.000000, sometimes 105.000000 x 30.000000, and so on.
This would be very understandable if items inside the window were being snapped to pixel alignments (to reduce aliasing or whatever) when the window position was fractional - but the mouse cursor position (thus the requested tooltip window position) is always a whole number and the window size still varies.

@ocornut
Copy link
Owner

ocornut commented Mar 22, 2015

I fixed a bug where they would be definitively wrong on the first frame, so at least they shouldn't be negative. But ImGui::GetWindowSize() gives you the size of the window at time of the first Begin() of the frame, otherwise it would vary depending on when you call it.

@ocornut
Copy link
Owner

ocornut commented Mar 22, 2015

I'm on it ! Fix soon.

@ocornut
Copy link
Owner

ocornut commented Mar 22, 2015

Fixed the bugs!
You will still get a small / empty size on the first frame the window is created, it doesn't have a size yet.
So your first example isn't fixed.

@adamdmoss
Copy link
Contributor Author

Thanks, 5737a79 + 072c57b totally fixes the app tooltip wrapper. :) Woo!
(I haven't re-tested the wiggling size problem - it's not causing me any pain, it just seems odd.)

I wasn't aware that GetWindowSize() gives you the size of the window at the time of the first Begin(); I was expecting that it varies depending on when you call it. But the current behaviour is fine with me anyway, now that I know what that is supposed to be. :)

Thanks!

@ocornut
Copy link
Owner

ocornut commented Mar 22, 2015

I could add a window to return "window->DC.CursorMaxPos - window->Pos", that would be the window extents at the time of the call (the "current" size).

@adamdmoss
Copy link
Contributor Author

That was what I thought the call was doing, but I don't have a use where I really really need it to behave like that - better to keep it simpler and document it more explicitly, perhaps.

@ocornut
Copy link
Owner

ocornut commented May 2, 2015

FYI I reorganised the Begin() functions which was full of traps (subtle ordering dependencies). It should be better and healthier now but there is the possibility that I've created bugs or changes of behavior related to window size. Let me know if you notice anything unusual.

The changes are spread over many commits ending with this
d84b573
(spreading them should make it easier to bissect for bugs shall we need to)

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

No branches or pull requests

2 participants