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

glfwSetKeyCallback triggers multiple key events after holding a key down #747

Closed
larsjarlvik opened this Issue Apr 21, 2016 · 16 comments

Comments

Projects
None yet
9 participants
@larsjarlvik
Copy link

larsjarlvik commented Apr 21, 2016

I just implemented camera movements and noticed that the camera moved forward for a bit after releasing W. After some investigation I noticed that glfwSetKeyCallback triggered another shorter sequence of GLFW_PRESS, GLFW_REPEAT and GLFW_RELEASE after I've release the key. The longer I hold the key the longer the second sequence is.

To make sure it wasn't something in my code I downloaded the getting started example and added a simple printf("%i ", action);

The output looked like this:

1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 1 2 2 2 2 0

Where the first 0 is when I actually released the key and the rest of the sequence are phantom key events.

I'm running GLFW 3.1.2 using the offical package on ArchLinux x64

@dmitshur

This comment has been minimized.

Copy link
Collaborator

dmitshur commented Apr 22, 2016

I just implemented camera movements and noticed that the camera moved forward for a bit after releasing W. After some investigation I noticed that glfwSetKeyCallback

This may be not directly related to the issue, but key callback is designed for text entry, so holding down a key will produce GLFW_REPEAT events. If you want to achieve frame-rate-independent camera movement, you'd likely want to use button callback and perform time-adjusted movements based on whether the buttons are pressed or released. Edit: This is invalid, I confused key and char callbacks.

The extra 1 2 2 2 2 0 phantom key events may be a legitimate issue with the key callback, however (at a glance, I haven't tried to reproduce).

@larsjarlvik

This comment has been minimized.

Copy link
Author

larsjarlvik commented Apr 22, 2016

As I understand from http://www.glfw.org/docs/latest/input.htm glfwSetKeyCallback is for keyboard input while glfwSetCharCallback is for text input with encoding etc. I can't find a button button callback in the docs for keyboard, just mouse.

I've implemented it in the way that I have a bool array which I set the current key to true on GLFW_PRESS and false on GLFW_RELEASE. The problem is that due to the issue I'm experiencing it's set to true twice, first correctly and after that another shorter time after I've released the key which makes the camera move a bit further than it should.

Also the longer I hold the key the longer the false keydown will be. It also seems a bit FPS dependent as it's lot less shorter if I turn off vsync.

@dmitshur

This comment has been minimized.

Copy link
Collaborator

dmitshur commented Apr 22, 2016

Apologies, what I said was completely incorrect because I confused "key" and "char" callbacks. I thought it was "button" and "key".

Too many context shifts. :P

As I understand from http://www.glfw.org/docs/latest/input.html#input_keyboard glfwSetKeyCallback is for keyboard input while glfwSetCharCallback is for text input with encoding etc.

That's correct.

@elmindreda

This comment has been minimized.

Copy link
Member

elmindreda commented Apr 22, 2016

Can you reproduce this with the events test? If so, please post the output.

@elmindreda elmindreda self-assigned this Apr 22, 2016

@larsjarlvik

This comment has been minimized.

Copy link
Author

larsjarlvik commented Apr 22, 2016

@elmindreda sorry what's the events test? I'm new to GLFW and quite rusty at C++, was a while ago so I need some more explanation.

@Spartan322

This comment has been minimized.

Copy link

Spartan322 commented Apr 22, 2016

Events Test

Also, don't you mean C?

@larsjarlvik

This comment has been minimized.

Copy link
Author

larsjarlvik commented Apr 24, 2016

Hehe, I do, got it mixed up in my head as I'm doing a bit of both at the moment.

However I've ran the events test and I couldn't reproduce the error. I investigated a bit further and found out that it only occurs when I have glfwSwapBuffers in my game loop.

Here's the output when I run it without changing any code, everything seems fine here:
http://pastebin.com/raw/7XXMgvee

And here's the output when I add glfwSwapBuffers to my code:
http://pastebin.com/raw/bW4GMZmK

Both times I just pressed W once for 3 seconds.

@ghost

This comment has been minimized.

Copy link

ghost commented May 29, 2016

Engo has the same unexpected output results as the test mentioned here. I could not see the bug in GLFW so did some extra testing. These are the results: https://gist.github.com/nitya-dev/094c12771e37fff8c06d8f6a02cd2cbf

Seems like this is upstream in the xorg server ?

@rdbv

This comment has been minimized.

Copy link

rdbv commented Jun 12, 2016

I have the same problem with glfwSetKeyCallback function.
Used GLFW version: 3.1.2 under Ubuntu 16.04, but problem exists on Debian too.
Code with bug: http://pastebin.com/PBTjhN6y
Example bugged output (W was pressed ~3 secs): http://pastebin.com/jEqYAqwi
Propably this can be solved by using some state machine, but is quite annoying when using controls in camera in OpenGL, and i don't want to write bug-specific code.

Thanks in advance :)

@elmindreda

This comment has been minimized.

Copy link
Member

elmindreda commented Aug 2, 2016

I cannot reproduce this.

@elmindreda elmindreda added the waiting label Aug 2, 2016

@elmindreda elmindreda removed the waiting label Sep 1, 2016

@ThomsV

This comment has been minimized.

Copy link

ThomsV commented Nov 7, 2016

I can reproduce it and it only happens if the rate at which glfwPollEvents() is called is low. In my case if it's less than ~50 refreshes per second. So the following will give phantom key-presses:

while (running)
{
glfwPollEvents();
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}

@jrkoenig

This comment has been minimized.

Copy link

jrkoenig commented Dec 10, 2016

Calling glfwPollEvents() at 2fps (aka add a 500ms sleep to the main loop) seems to trigger it reliably on X.Org X Server 1.18.4, running on Ubuntu 16.10 with GLFW 3.2.0.

The solution is literally starring us in the face.

            if (window->x11.ic)
            {
                // HACK: Ignore duplicate key press events generated by ibus
                //       Corresponding release events are filtered out by the
                //       GLFW key repeat logic
                if (window->x11.last.keycode != keycode ||
                    window->x11.last.time != event->xkey.time)
                {
                    if (keycode)
                        _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
                }
            ...

Sure enough, if you disable window->x11.ic by disabling im globally (if (XSupportsLocale()) -> if (XSupportsLocale() && 0) in x11_init.c), then there are no phantom keypresses. You can also see that each phantom keypress has an old timestamp exactly identical to that of a keypress that was already received and processed, validating that HACK comment.

My guess is ibus doesn't send the keypress until the previous event is actually removed from the queue/forwarded/whatever, so it takes N processing loops to clear N keypress repeats. When FPS > key repeat rate, there is no issue, but otherwise they pile up and it takes many event loops to clear the backlog.

The solution is rather simple. Rather than filtering based on the last received timestamp, instead discard any events older by more than say 10ms than the most recent key event received, to account for noisy timestamps. The current code assumes the duplicate keypresses are adjacent in the event stream, which is false at low FPS. I'll make a PR soonish.

@elmindreda elmindreda added this to the 3.3 milestone Dec 10, 2016

@elmindreda

This comment has been minimized.

Copy link
Member

elmindreda commented Dec 11, 2016

@jrkoenig Thank you! I've added this to 3.3 thanks to your findings, but I have other issues to close before this one.

@ZenToad

This comment has been minimized.

Copy link

ZenToad commented Mar 23, 2017

I'm not sure it matters at this point, but I can confirm that this is a bug on Ubuntu 16.04 and the fix did work for me, using 3.2.1

@elmindreda elmindreda added this to High Priority in Review Queue Mar 23, 2017

@elmindreda elmindreda removed this from High Priority in Review Queue Mar 26, 2017

@elmindreda elmindreda added the verified label Mar 27, 2017

@elmindreda

This comment has been minimized.

Copy link
Member

elmindreda commented Mar 27, 2017

This should be fixed now with 4ff66a7.

@dulsi

This comment has been minimized.

Copy link

dulsi commented Jul 17, 2018

Any time frame on 3.3? Alternatively could a 3.2.2 release be made? Right now glfw is not that useful on Fedora Linux due to the phantom key presses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.