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

Repeated key press events #1220

Closed
jeffparsons opened this issue Jan 17, 2018 · 8 comments
Closed

Repeated key press events #1220

jeffparsons opened this issue Jan 17, 2018 · 8 comments

Comments

@jeffparsons
Copy link

Holding down a key in Piston will begin to generate multiple spurious input events after short delay. This behaviour is like the common "key repeat" feature found in most text areas in GUIs, but is presumably only accidentally happening in Piston, given that it makes it impossible to tell which are the actual press events, and which are repeats. (And previous discussion also suggests it is not deliberate — see below.)

Observed on Mac OS X latest (10.13.2) and previous versions. Not sure if this affects other platforms. Not sure if it's caused by Piston itself, or some underlying input library. Maybe it only shows up on some backends.

Code

extern crate piston;
extern crate piston_window;

use piston::input::*;
use piston_window::*;

fn main() {
    let mut window: PistonWindow = WindowSettings::new(
        "piston: unwanted key repeats",
        [200, 200]
    )
    .exit_on_esc(true)
    .build()
    .unwrap();

    window.set_lazy(true);
    while let Some(e) = window.next() {
        if let Event::Input(input) = e {
            if let Input::Button(button_args) = input {
                if let Button::Keyboard(key) = button_args.button {
                    // Hold down a key, and see the message repeated in your terminal.
                    println!("Key event: {:?} {:?}", key, button_args.state);
                }
            }
        }
    }
}

How to reproduce

Just hold down any key, and watch the terminal output.

Output

Key event: J Press
Key event: J Release
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Release
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Press
Key event: J Release
Key event: Escape Press

Previous discussion

In a previous discussion somebody believed that they'd seen key repeat behaviour in Piston, then later concluded that they were thinking of some other library.

A relevant parallel seems generating keypress events - SDL2/piston send repeated keypress events as a convenience when the same key is being held down. (I'd argue that this behaviour is the type you don't want - since it's "overloading" an existing event rather than using a different one such as KeyRepeat.)

And later...

I was flat wrong here, keypress events do not autorepeat. Apologies, I must have been thinking about a different library in my past.

And from someone else...

I was curious about the key repeat, because I couldn't remember it.

This combined with the evidence above makes me suspect it may be a platform- or backend-specific bug. I'll try on another OS and post results here.

@jeffparsons
Copy link
Author

Gist with cargo run-able code here: https://gist.github.com/jeffparsons/e4fa304e11efea677e3f0a4cc18c9ed5

@filippo-orru
Copy link

This is super annoying and proving harder to fix than I thought. Please fix this. Press and release events should behave as such. Only call them once for every event.

@bvssvni
Copy link
Member

bvssvni commented Dec 20, 2019

Separating the events would be cleaner. You can also test with the "user_input" example: https://github.com/PistonDevelopers/piston-examples/tree/master/user_input

We need a solution that is consistent across window backends.

@bvssvni
Copy link
Member

bvssvni commented Dec 27, 2019

I've done some investigation: This is an issue with the Glutin backend only.

The SDL2 and GLFW backends emits key presses once. Piston uses "text" events for text editor behavior, which includes repeats. Key presses (not "text" events) should therefore only be emitted once in Piston. No design changes are needed in the Piston core. The reason this bug appears in the Glutin backend is an issue with the Glutin API.

Currently, it is not possible to tell the difference between key presses and key repeats in Glutin without using heuristics. This might make it problematic to fix in the backend.

The current state of this issue in Glutin/Winit is a proposal to change the API.

Related issues (Glutin and Winit):

@bvssvni
Copy link
Member

bvssvni commented Dec 27, 2019

A heuristic solution to fix the behavior in the Glutin backend could use a HashSet<u32> to store previously emitted press events before key release. When the window loses focus (alternative: receives focus), the hash set should be cleared.

@santiagocezar
Copy link

santiagocezar commented Jul 29, 2020

I was having the same problem and found this issue.
At least on Linux X11 and Wayland only the last key pressed is repeated, so only one press should be stored, like ggez does

@bvssvni
Copy link
Member

bvssvni commented Apr 14, 2021

A common workaround is to store a state whether a button is pressed or not. For example, in 2D platform games it is common to use a vector to represent the state of up/down/right/left and all game logic depends on this state instead of button presses directly.

A less common workaround is to fork the Glutin backend in Piston and make the modifications for a specific project. These kinds of problems is one of reasons Piston uses a modular architecture.

I believe the issue was delayed because a fix in Glutin was expected.
This is still an issue with Glutin (see rust-windowing/glutin#641, which was closed).
It does not seem that Glutin will fix this, so I think it is time to compensate in the Piston backend.

This needs careful analysis because platforms where key release behavior is different might enter a state where some button is believed to pressed when it is in fact released.

I tested this on "user_input" on OSX 10.11.6 and found the following:

  • It is not a problem in the SDL2 or GLFW backend
  • The key release behavior when unfocusing the window is different:
    • Glutin emits the key release event only when the key is released unfocused
    • SDL2 and GLFW emits the key release twice, once on unfocus and when the key is released unfocused

Redundant release events do not usually cause problems and we have not determined yet the best behavior for key released in combination with window unfocus events. So, I think we should focus on press events.

One idea is to use the most straightforward method suggested by PistonDevelopers/glutin_window#183 and recommend the less common workaround (forking the Glutin backend) for people who experience problems on custom platforms.

@bvssvni
Copy link
Member

bvssvni commented Apr 17, 2021

Closed by PistonDevelopers/glutin_window#201

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

No branches or pull requests

4 participants