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

Cursor inside application is inverted. #98

Open
SSBMTonberry opened this issue Jul 27, 2019 · 15 comments
Open

Cursor inside application is inverted. #98

SSBMTonberry opened this issue Jul 27, 2019 · 15 comments

Comments

@SSBMTonberry
Copy link

Hello, Elias!
Thank you for an amazing library!

I just updated IMGUI-SFML to the latest version (latest commit, not release), and noticed that the cursor inside the application was "mirrored". Instead of pointing towards the left, it points towards right. I've tried to take a screenshot of this, but none of the screenshot apps I have were able to take a screenshot with the cursor inside the app. I first noticed this inside my application, but I compiled the imgui_sfml_example and saw the same result. As for version I'm using the IMGUI dock branch from mid march this year. That was marked 1.69 WIP on its demo.

Do you have any idea how this happened?

Additionally: The reason why I updated was because I've been experiencing that my applications using ImGui and SFML with your binding sometimes booted being unable to take any events after they are booted with an older version. Didn't happen all the time, but when it happened, it could be solved by unfocusing the application itself and refocus. Do you know if this is something that was due to a bug in ImGui-SFML? Haven't tested it with the newest version, but I experienced it with some older version I cannot put a date on.

  • Robin.
@SSBMTonberry
Copy link
Author

Just tested it on the Releases 2.0.2 and 2.0.0. Same issue.

@eliasdaler
Copy link
Contributor

Hello. What system are you using? Can you try to compile ImGui's SDL example and test cursors in ImGui demo window? My guess is that your system/distro has cursor ids messed up and I can't to anything with it.

Try doing this:

ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;

This will prevent ImGui-SFML from trying to use SFML's cursor change functionality.
Also you can alternatively do this:

ImGuiIO& io = ImGui::GetIO();\
io.MouseDrawCursor = true;

This will make ImGui-SFML draw cursor instead of using OS cursor. The cursor might be a bit more laggy because of that, but it'll look consistent.

@SSBMTonberry
Copy link
Author

I'm using Manjaro Linux as my OS.

Compiled the last version for imgui with the sdl_opengl3 example, and it works as intended there. I do notice that it uses the regular OS-mouse as the default when not howering textboxes or something resizable tho.

Didn't experience this issue in an older version of this lib. It definitely draws the ImGui-cursor, and changes the cursor correctly when you for instance is on a corner trying to resize. The only strange thing is that the cursor itself is mirrored when in the normal state.

I created a workaround, though, which basicly makes it just draw the OS-cursor when in certain states. What I did was:

void updateMouseCursor(sf::Window& window) {
    ImGuiIO& io = ImGui::GetIO();
    if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0) {
        ImGuiMouseCursor cursor = ImGui::GetMouseCursor();

        if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) {
            window.setMouseCursorVisible(false);
        } else {
            window.setMouseCursorVisible(true);

            sf::Cursor& c = s_mouseCursorLoaded[cursor]
                                ? *s_mouseCursors[cursor]
                                : *s_mouseCursors[ImGuiMouseCursor_Arrow];
            
            //Force normal cursor in certain states
            if(cursor == ImGuiMouseCursor_Arrow || cursor == ImGuiMouseCursor_ResizeNWSE || cursor == ImGuiMouseCursor_ResizeNESW)
                window.setMouseCursor(sf::Cursor());
            else
                window.setMouseCursor(c);
        }
    }
}

You may be right that this is out of your control, but I don't think the error would be due to a cursor ID that is messed up, as the cursor shown is the right kind, just flipped/mirrored. But since ImGui itself shows the default OS cursor as default cursor in its examples, maybe it should be done in ImGui-SFML as well if the system is Linux (not sure how it is on the other systems).

But I honestly don't know the origin to the error. Just that the workaround I did above makes it look normal, as it just passes an empty sf::Cursor(), forcing it to use the regular cursor in certain states. Might be better ways to solve this, though.

Just checked the older version of Imgui-SFML, and it seems like it mostly just draws the default cursor for the OS, but due to that it appears fine. With the workaround it's actually a bit more fancy than it used to be :)

@eliasdaler
Copy link
Contributor

Well, this means that sf::Cursor::Arrow doesn't look right... Can you make a simple SFML application which will only change the cursor to sf::Cursor::Arrow and see it it chooses the wrong one?

I'm not sure that your fix is correct, because the cursors should be loaded explicitly. As far as I know, empty sf::Cursor is in invalid state and when you try to release it, you get warnings/errors on some systems...

And FYI, I think that ImGui-SFML's cursor looked right to you before 2.0, because it didn't use sf::Cursor functionality?

@SSBMTonberry
Copy link
Author

yes, sf::Cursor::Arrow is what looks weird here. Everything else seems to look just fine really.

I think you are right that it looked right before because you didn't use the sf::Cursor functionality at all. I don't think my workaround is by any means a good way to solve the problem, but for now it was the only thing I could think of as a quick solution. Not sure about the consequences it might have, but it seemingly does the job.

I created a simple application using this modified code of your lib

void updateMouseCursor(sf::Window& window) {
    ImGuiIO& io = ImGui::GetIO();
    if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0) {
        ImGuiMouseCursor cursor = ImGui::GetMouseCursor();

        if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) {
            window.setMouseCursorVisible(false);
        } else {
            window.setMouseCursorVisible(true);

            sf::Cursor& c = *s_mouseCursors[ImGuiMouseCursor_Arrow];
            window.setMouseCursor(c);

        }
    }
}

As I would expect, it now only shows an inverted cursor, where it points in a mirrored direction in all states (same cursor, and never changes).

I also just tried to force the sf::Cursor::Arrow, and it actually shows the same mirrored cursor. Which means that it's not really your library that is the cause to the problem. Could it be a solution to just force the regular OS-arrow instead of sf::Cursor::Arrow, since it apparently is weird on some systems?

My simple vanilla SFML test program:

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
    // ... create window as usual ...
    sf::Cursor cursor;
    if (cursor.loadFromSystem(sf::Cursor::Arrow))
        window.setMouseCursor(cursor);

    while(window.isOpen())
    {
        // Process events
        sf::Event event;
        while (window.pollEvent(event))
        {
            // Close window: exit
            if (event.type == sf::Event::Closed)
                window.close();
        }
        // Clear screen
        window.clear();
        // Update the window
        window.display();
    }

    return 0;
}

What do you suggest?

@eliasdaler
Copy link
Contributor

There are two options I can do.

  1. Ability to disable sf::Cursor functionality at all
  2. Ability to map ImGui cursors to custom SFML Cursor. Please try all possible sf::Cursor types. Is there one that looks like a non-mirrored arrow?

@SSBMTonberry
Copy link
Author

Okay, I've tried every possible sf::Cursor now. The only supported arrow that turns out weird is sf::Cursor::Arrow. All the others are completely fine, and looks good. If I use a cursor not supported by the OS, I just end up getting the regular arrow-cursor (non-mirrored and all fine).

sf::Cursor::ArrowWait looks like a non-mirrored arrow, due to not be supported in Linux. Apparently this cursor is only supported on Windows.

Reference to the SFML documentation on the cursors.

    ////////////////////////////////////////////////////////////
    /// \brief Enumeration of the native system cursor types
    ///
    /// Refer to the following table to determine which cursor
    /// is available on which platform.
    ///
    ///  Type                               | Linux | Mac OS X | Windows  |
    /// ------------------------------------|:-----:|:--------:|:--------:|
    ///  sf::Cursor::Arrow                  |  yes  |    yes   |   yes    |
    ///  sf::Cursor::ArrowWait              |  no   |    no    |   yes    |
    ///  sf::Cursor::Wait                   |  yes  |    no    |   yes    |
    ///  sf::Cursor::Text                   |  yes  |    yes   |   yes    |
    ///  sf::Cursor::Hand                   |  yes  |    yes   |   yes    |
    ///  sf::Cursor::SizeHorizontal         |  yes  |    yes   |   yes    |
    ///  sf::Cursor::SizeVertical           |  yes  |    yes   |   yes    |
    ///  sf::Cursor::SizeTopLeftBottomRight |  no   |    yes*  |   yes    |
    ///  sf::Cursor::SizeBottomLeftTopRight |  no   |    yes*  |   yes    |
    ///  sf::Cursor::SizeAll                |  yes  |    no    |   yes    |
    ///  sf::Cursor::Cross                  |  yes  |    yes   |   yes    |
    ///  sf::Cursor::Help                   |  yes  |    yes*  |   yes    |
    ///  sf::Cursor::NotAllowed             |  yes  |    yes   |   yes    |
    ///
    ///  * These cursor types are undocumented so may not
    ///    be available on all versions, but have been tested on 10.13
    ///
    ////////////////////////////////////////////////////////////

Of the two options, I think the second option is the most appealing :)

@SSBMTonberry
Copy link
Author

Did a new workaround, that gives me a better result and should be less risky, based on the information I wrote above.
It's inside the Init() function:

#if __linux__
        loadMouseCursor(ImGuiMouseCursor_Arrow, sf::Cursor::ArrowWait);
        loadMouseCursor(ImGuiMouseCursor_ResizeNESW,sf::Cursor::SizeAll);
        loadMouseCursor(ImGuiMouseCursor_ResizeNWSE,sf::Cursor::SizeAll);
    #else
        loadMouseCursor(ImGuiMouseCursor_Arrow, sf::Cursor::Arrow);
        loadMouseCursor(ImGuiMouseCursor_ResizeNESW, sf::Cursor::SizeBottomLeftTopRight);
        loadMouseCursor(ImGuiMouseCursor_ResizeNWSE, sf::Cursor::SizeTopLeftBottomRight);
    #endif

    loadMouseCursor(ImGuiMouseCursor_TextInput, sf::Cursor::Text);
    loadMouseCursor(ImGuiMouseCursor_ResizeAll, sf::Cursor::SizeAll);
    loadMouseCursor(ImGuiMouseCursor_ResizeNS, sf::Cursor::SizeVertical);
    loadMouseCursor(ImGuiMouseCursor_ResizeEW, sf::Cursor::SizeHorizontal);

Using SizeAll for other unsupported cursors used for resizing on Linux, and set the cursor to the non-existing cursor sf::Cursor::ArrowAwait to actually get a regular non-mirrored cursor. It's a kinda silly workaround to use sf::Cursor::ArrowAwait to achieve this, but it does the job!

@eliasdaler
Copy link
Contributor

This is a very strange workaround... This will totally mess up cursors for people on other distros/WMs (which ones are you using, btw?)

@SSBMTonberry
Copy link
Author

It is a very strange workaround indeed, but if what they write is correct (and I understand it correctly), the signal for sf::Cursor::ArrowWait doesn't exist as a signal at all in Linux. Keep in mind that behind every desktop environment and distro, they all use a common system: X11. If X11 doesn't support this cursor state, I think this workaround should work about the same on every Linux-distro. I am not sure if there are desktop environments that are able to access the state nonetheless, though.

I'm using this as a workaround for now, because I cannot think of a better solution which doesn't involve attaching a custom cursor. If you got other suggestions, I'll be happy to test them for you :)

I'm using Manjaro Linux (an Arch Linux based distro) with the i3 desktop environment.

@SSBMTonberry
Copy link
Author

SSBMTonberry commented Jul 30, 2019

Come to think of something. If I do not change the cursor state at all, I'll just have my default cursor. But if I change to sf::Cursor::Arrow manually, the mirrored cursor I get is not the same as my default, in fact it actually looks like the cursor used in X11 (but mirrored). Which is the base gui-system you get if you don't have any desktop environment or a window manager. I think the cases of actually manually setting the state of the mouse are pretty rare, and in addition: The system they are doing the least testing on is obviously Linux-based systems...

The mirrored arrow cursor looks just like this arrow cursor:
image

@eliasdaler
Copy link
Contributor

Seems very complicated to try to fix on ImGui-SFML's level. It's more of SFML bug, to be honest, and I don't want to have workaround which might break at some point.

So, my best way of fixing this is this:

  1. Allow to disable sf::Cursor functionality entirely
  2. Allow to map ImGui cursor enum value to any sf::Cursor type

Btw, did you try the stuff I've suggested previously? What are the results?

// A

ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;

// B

ImGuiIO& io = ImGui::GetIO();
io.MouseDrawCursor = true;

@SSBMTonberry
Copy link
Author

I agree with you 100 percent! :)

I did not try the stuff you mentioned, but I'll do it now, just to give you a heads up on the result.

I just reported the bug to SFML btw:
SFML/SFML#1606

@SSBMTonberry
Copy link
Author

//A
Adding the io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange made it work just like in the old version, where you have the regular cursor on everything. In other words: Looks good 👍

//B
This actually looks even better than A! Seems like it changes to ImGui's own cursor, which changes correctly with each state, which I think is fine :) Looks good

@eliasdaler
Copy link
Contributor

Okay, nice.
I think I'll add these options to README. I'll also take a look at SFML's bugs and maybe find a better workaround for ImGui-SFML... :)

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