-
Notifications
You must be signed in to change notification settings - Fork 436
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
Plaftorm: Add cursor management support #383
Conversation
Codecov Report
@@ Coverage Diff @@
## master #383 +/- ##
=========================================
+ Coverage 72.24% 76.1% +3.86%
=========================================
Files 350 345 -5
Lines 18634 16919 -1715
=========================================
- Hits 13463 12877 -586
+ Misses 5171 4042 -1129
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, this is great!
For other platforms:
-
Glx / XEglApplication -- don't care, those lack a lot of features anyway and are there just for barebones app setup on embedded systems (like Raspberry Pi and such) ... and then everybody would install GLFW/SDL anyway
-
AndroidApplication -- this would be useful only for Androids with a mouse connected. I think that's so rare there isn't a reason to bother either :)
-
Emscripten -- looking at their APIs, there doesn't seem to be any way to do this. A random idea -- this could be done similarly to how
setContainerCssClass()
works, adding a CSS class to the<canvas>
element, and then expanding theWebApplication.css
for example like this:#canvas.cursor-crosshair { cursor: crosshair; } #canvas.cursor-ibeam { cursor: text; }
This of course depends on if you have Emscripten set up or not (I don't remember if you do, sorry). If you don't, i can add this myself post-merge :)
Last thing: I'd like to put a stable release out after the weekend. Is it okay if this waits post-release (to have enough time to iron out issues etc.)? Or do you need it in the release?
Thanks for taking time to review this :D
Unfortunately I don't have Emscripten set up and I don't have really a clear idea on how to do it.
Yeah, I'll be fine. I can always use the --Head, so no problem there. |
Okay, then I can do the Emscripten part myself, no worries :) |
Well, I think that I made everything... almost. I discovered that imgui also wants to show/hide the cursor as he needs to, so maybe I can add a showCursor() and hideCursor() as well |
Is that orthogonal to the cursor type? Since it could be done via Btw., I spotted some cursor-related APIs in GlfwApplication, isn't this hiding/showing there already? |
Yeah, I can make it relative to the type adding a Cursor::Hidden (and a Cursor::Disabled for glfw that has this extra option that can hide the cursor and enable unlimited mouse movement).
Yep, there is already a cursorMode() inside of GlfwApplication::Configuration, but you can only change the mode on creation and not in real time. |
Hmm. SDL has that as setMouseLocked(), fortunately that's not just on creation. (Having only a possibility to do that once in Configuration for GLFW seems kinda useless, heh.) If you want to implement this too, what about the following, to have it consistent for both:
And with this, I think it'd be good to have a Then the |
SDL_SetRelativeMouseMode() is not exactly identical to glfw's Disabled state: glfw locks the cursor on it's position and make it invisible (even moving the mouse, the cursor stays hidden and at the same position); SDL_SetRelativeMouseMode() makes the cursor position only be relative to the window, so it can be moved and it will interact with everything that's in the window. The closest we can get is using SDL_SetWindowGrab, it locks the cursor on it's current position as glfw's Disabled state does (or in the top left of the windows if the cursor was outside of the window when the function is called, instead of the center of the screen that glfw uses as default, but I think that this is an insignificant difference). |
Oh, ok, nevermind, actually the glfw's Disabled state is the same as the SDL_SetRelativeMouseMode, but if it's called multiple time (I was testing it in an ImGui context) the cursor gets like resetted to the last position, but with SDL_SetRelativeMouseMode actually not and it works well |
If you look at setMouseLocked(), it calls both We could also postpone this part to later, if you don't feel like digging deep into this stuff. |
After having documented better I found the real differences:
So the problem here is Glfw, in their documentation I haven't found a real alternative to SDL_SetRelativeMouseMode, so the only thing that we could do is to fake it if we really want to.
Maybe for now I could add a Cursor::HiddenLocked for sdl using the SDL_SetRelativeMouseMode() and a Cursor::HiddenUnlimited (?) using the GLFW_CURSOR_DISABLED? |
Isn't then |
That's what I'd expect either from HiddenLocked, and it's what setMouseLocked() currently does so it's correct. GLFW_CURSOR_DISABLED has unlimited movement as well, but they do this as the absolute position of the cursor is unlimited and not limited to the window. E.g. with setMouseLocked() using the MouseMoveEvent::position(), you'll get values within the window size, but with GLFW_CURSOR_DISABLED you'll get an absolute position of like if the cursor is moving outside of the window and even outside the screen. This is what I meant. |
Which, as far as I understand, means Then, as of 89d4a75, |
Ok then, now it should be good to go!
Well, you're right, reading the description I understand that too, but actually, from my test, the absolute position actually changes, but remains within the size of the window (at least on macOS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last three minor things and then I think it's good to go as well 🎉 Thank you!
Done |
Thanks a lot! Do you have the ImGuiIntegration counterpart as well? :) So I have something to test with when I get to implementing the Emscripten side. |
I made a really bad version inside my application just for testing (so not actually in the ImGuiIntegration). But I have some concerns on doing it inside ImGuiIntegration, like, how could I manage to access the Application::Cursor without having to include the Sdl2Application? Because I was thinking to make another CursorMap to map the Application::Cursor to the imgui's cursor flags (taking note that imgui uses some cursors that sdl has but glfw doesn't have). Or maybe I'm thinking it in a wrong way? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heh. So I thought I'd look into how the ImGuiIntegration
part could be implemented ... and ended up doing the whole thing: mosra/magnum-integration#56 😆
What's important, while integrating your code I thought it would make sense to move the cursor-related stuff into the "Mouse handling" sections and then discovered there's GlfwApplication::warpCursor(const Vector2i&), calling glfwWarpCursor(). Since you did all this locking/warping/window grabbing investigation, can you tell how does this API fit into the rest? Should we leave it there? Call implicitly to be consistent with what SDL's API do? Expose some equivalent on SDL side?
Sorry that new problems keep piling up 😅
Yep, it makes more sense
I think that it's good, even because there is SDL_WarpMouseInWindow for SDL, so I could just add a warpCursor() in there as well and improving the unified API. |
Ohh! So warp is "mouse goes out on one side but comes back on the other", right, not related to mouse locking or cursor hiding or that. Yup, agree on adding the equivalent on SDL side. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! If I get some extra free time to finish the Emscripten part, this could go in to this release already.
Merged in 40bfa7a, sorry for the delay caused by all the release management stuff. In addition I implemented Emscripten support in 04827d3 and c091ed0 (wow, CSS has 36 cursor types), plus deprecated the old, inconsistent and useless APIs in favor of your new ones in 8d9d247 and c4e3e3c. Next I'm going to merge the ImGui side and upload an updated example. Thank you for this! |
Platform support:
AndroidApplicationIt's rarely usedGlxApplicationEmscriptenApplicationIt'll be made by mosraXEglApplicationThe main usage for this (that is the main reason on why I implemented this) is for the ImGuiIntegration, because right now when hovering the edges of the windows/other draggable elements the cursor doesn't change due to the lack of this feature.
I'm not entirely sure about how good it's implemented, e.g. the way I constructed the array using the last enum element to get the size, and the whole switch-case that I needed to make (yeah, basically everything).
Also, I was thinking about adding the cursor creation in the Application constructor as well, using the Configuration class, but even there I was unsure if it was a good idea or not.