-
Notifications
You must be signed in to change notification settings - Fork 523
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
Inconsistent grabbing behavior in demos (click and drag property) #608
Comments
Which demo are you experiencing this on? The SDL one? To my knowledge, |
I've experienced the issues with SDL on Linux, but as explained above, this problem is not exclusive to SDL and applies to all demos that manage grab/ungrab state changes in this way. The demos that handle the grab state changes within the event loop (which may get skipped), can/will lead to missed grab state changes. I've made an overview of the affected demos: Demos Incorrectly Handling Grab/Ungrab State (These demos handle grab/ungrab state within the event handling loop):
Demos Correctly Implementing Grab/Ungrab State (These demos handle grab/ungrab state per frame, ensuring the state changes won't get missed):
Demos That Do Not Implement Grabbing:
I guess the correct solution would be to move the grab state handling out of the event handling function, and into its own function which should then be called outside of the event loop. Here is an example:
This would make the logic equivalent to the glfw demos I guess this would be a reasonable approach to use fixing the demos and making a pull request? |
Thanks for the indepth analysis! If you push up a pull request, I'd be happy to test it out on SDL & Linux |
I've opened a pull request, fixing the issue with the SDL demos. Additionally, the cursor is now correctly returning to its exact original coordinates post-grab, (It wasn't before, which was primarily obvious after long drags). This was achieved by: ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y; (Full function)NK_API void
nk_sdl_handle_grab(void)
{
struct nk_context *ctx = &sdl.ctx;
if (ctx->input.mouse.grab) {
SDL_SetRelativeMouseMode(SDL_TRUE);
} else if (ctx->input.mouse.ungrab) {
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_WarpMouseInWindow(sdl.win, (int)ctx->input.mouse.prev.x, (int)ctx->input.mouse.prev.y);
} else if (ctx->input.mouse.grabbed) {
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
}
} This approach is the same as the handling found in the GLFW demos: nuklear_glfw_gl2.h#L360 This should fix grabbing for the SDL demos and aligns the SDL demo's logic with the GLFW demos. I can take a look at the remaining sfml and x11 demos if you're happy with the changes of the pull request? |
Thanks @paccerdk ! Really appreciated. I have commented in your PR and I think it looks good. So feel free to do the same for sfml and x11 demos. If you will not have the bandwidth, just tell us and we will merge the PR as is and/or extend it to sfml and x11 demos too. |
Sure, i can probably do it within the week - if not, ill let you know |
I had a look at the SFML demos, but it turns out that grabbing isn't actually implemented. It looks like it was started but never finished. It tries to call I have SFML up and running now, so I had a look at implementing grabbing codeNK_API void
nk_sfml_handle_grab(void)
{
struct nk_context* ctx = &sfml.ctx;
if (ctx->input.mouse.grab) {
sfml.window->setMouseCursorVisible(false);
sfml.window->setMouseCursorGrabbed(true);
} else if (ctx->input.mouse.ungrab) {
sfml.window->setMouseCursorGrabbed(false);
sf::Mouse::setPosition(sf::Vector2i((int)ctx->input.mouse.prev.x, (int)ctx->input.mouse.prev.y), *sfml.window);
sfml.window->setMouseCursorVisible(true);
} else if (ctx->input.mouse.grabbed) {
// does not work well with the way mouse movement is currently handled in the event handler
// ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
// ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
}
} However, it wasn't as straightforward as I was hoping. This is partially because SFML doesn't have support for relative/delta mouse movement, requiring a bit different logic than some of the other implementations, possibly a changed mouse move event handler. I'll have another go at it, but if it's too problematic, then it might make sense to either just strip the unfinished implementation from the SFML demos or just leave them as is. In regards to the X11 demos, I had a quick look, and it seems like it should be straightforward to fix those. |
Looks like #609 was merged, that's probably for the best. I believe i have the SFML demos implemented and fixed now, and so is the majority of the X11 demos, however, there's been a lot of inconsistencies, one of the x11 demos generated an event every single cycle, i fixed that, another one of the x11 demos isn't implemented correctly, and the context is not used like in the other demos. It's going to take a while more, but i'm working on it when i have some spare time and energy. Would it be ok to keep this issue open? I'll update with info and make another pull request when its ready. |
There seems to be an issue with the implementation of grabbing behavior across several demos, particularly when this behavior is combined with relative movement (dragging an input value).
The problem primarily arises due to how the grab state (
nk_context
input.mouse.grab/ungrab
) is always reset, even if no event happens, leading to grab/ungrab potentially being missed in event handling, especially noticeable with frameworks like SDL.Issue Details
The issue occurs with the following sequence of events:
nk_input_button
which in turn causesnk_property_*
to set the grab state to1
(nk_true
) later in main loop.nk_input_end
is called, which resets the grab state to0
without being handled.Similarly, The same problem happens with the ungrab state
Impact Details
This is a problem for frameworks that do not automatically generate an event following a mouse down/up action. For instance, the SDL implementation requires two consecutive events for proper grabbing behavior. A scenario where the mouse is pressed down and then moved with more than 1 cycle in-between fails to maintain the grab/ungrab state, unlike when multiple events happen, such as a mouse move together with mouse down event.
Its an even bigger problem when a grab event gets handled, but the ungrab event doesn't, causing the mouse cursor to disappear permanently and staying in relative mode with the SDL demos
Solution
I wouldn't mind providing a pull request, but i'm not sure about the ideal way to implement the solution,
maybe someone more familiar with the framework might be able to suggest a more integrated solution than mine?
EDIT:
see better solution in #608 (comment)
Old solution
A simple way of solving it would be something like the following:
This approach only resets grab / ungrab when its been handled.
I believe the following issues are related:
These two has @vurtun mentioning that here is a problem:
vurtun/nuklear#203
vurtun/nuklear#631
#556
#512
The text was updated successfully, but these errors were encountered: