lemunozm / ruscii

Terminal graphics engine: build your games in the terminal!
Apache License 2.0
170 stars 15 forks source link

WSL2 Keyboard Input Bug: Missing Key Events #42

Open fadeevab opened 1 year ago

fadeevab commented 1 year ago

All examples hang in WSL2 environment, and no keyboard events are detected.

From my understanding, device_query is used to streamline keyboard events to the application thread. Is there a way to utilize crossterm features instead of device_query giving up some functionality (it would be cool to drop the X11 dependency)?

Overall, there should be a way to utilize the game loop without X11 dependency (basically, X11 is a non-obvious dependency having only a terminal in place).

fadeevab commented 1 year ago

@lemunozm I think device_query can be substituted with crossterm::event: poll + read, the events also contain additional information like https://docs.rs/crossterm/latest/crossterm/event/enum.KeyEventKind.html

fadeevab commented 1 year ago

@lemunozm Hi! A kindly reminder to look at this issue.

lemunozm commented 1 year ago

Hi!

X11 dependency is used to be able to handle release keys. crossterm only dispatches (or at least dispatched) the terminal events, and terminals don't know about "releasing" a button.

Nevertheless, not sure why crossterm defines a Release event when the own terminal does not generate such an event 🤔. Maybe some modern terminals are able to do so.

lemunozm commented 1 year ago

Searching about this I found this thread in stackoverflow

fadeevab commented 1 year ago

@lemunozm Thank you for your feedback!

FYI, I use Windows Terminal which, I hope, should be quite standard for WSL2 folks. Although, I haven't found whether it supports/generates "key up" events.

Overall, I feel that the absence of key-up events should not be a stopper of using your library, e.g. I would consume the game loop even having limited keyboard capabilities... The features might be introduced:

  1. Using device_query (with X11 dependency).
  2. Using cross_term (ignoring key-up events).

I was originally thinking to utilize any game loop to render custom stuff.

lemunozm commented 1 year ago

Overall, I feel that the absence of key-up events should not be a stopper of using your library

Probably you're right here. Just saying that the biggest braking features of ruscii is just the key-up event, so if you cannot use that feature, maybe there is a better option that is more supported or more powerful in other aspects (such as tui.rs or directly crossterm).

Right now, I have no free time to add new enhancements to this library, but if someone wants to work on that, I can review it and give support to the PR.

sebjwallace commented 1 year ago

Hey all, there's the option to use the console crate https://crates.io/crates/console

Although the type returned from stdout.read_char isn't compatible with the Key enum from ruscii (is it's a char type), it's still good enough to get going:

app.run(|app_state: &mut State, window: &mut Window| {
        if let Ok(character) = stdout.read_char() {
            match character {
                'w' => todo!("Up"),
                'a' => todo!("Left"),
                's' => todo!("Down"),
                'd' => todo!("Right"),
                'q' => app_state.stop(),
                _ => (),
            }
        }
}

I trialed raw device_query, which it seems is an internal dependency in ruscii, and I was getting the same problems... unsuprisingly. I'm on a mac, and even changing my accessibility settings didn't help. Anyways, hope the above helps.

alefnull commented 5 months ago

Right now, I have no free time to add new enhancements to this library, but if someone wants to work on that, I can review it and give support to the PR.

as it turns out, i just recently started learning Rust, and in the process, just published my first project which happens to use ruscii, called dvd-term. and while doing some testing today, i discovered while on my windows laptop, key events are responded to as expected, but when running my app in WSL or in an Ubuntu VM, i was unable to exit the app using any keyboard inputs i'd specified, or even good ol' ctrl+c.

i'm not entirely sure it's due to the same thing, but my guess is probably. i don't know if i'll be able to figure it out, but i may take a crack at working on this in whatever spare time i have.

Hey all, there's the option to use the console crate https://crates.io/crates/console

and i was happy to see an alternate recommendation, but sadly using that crate caused my app to not display at all, and hang on a blank screen until i hit one of the registered 'exit' keys. 😢

lemunozm commented 5 months ago

just published my first project which happens to use ruscii, called dvd-term

Wow! 🚀 You can create a PR if you want to add it into the "Projects Using ruscii" README section to share with other users examples of how to use ruscii

i was unable to exit the app using any keyboard inputs i'd specified, or even good ol' ctrl+c.

It's expected ctrl+c to not work, because ruscii puts the terminal in something called "raw mode", where input keys are not interpreted as usual. Nevertheless, the configured keys should work... 🤔

In MacOS (unix-based) I needed to enable for the terminal some accessibility functions to make the keys work. It's like X11 needs some special privileges in some machines, maybe the issue is similar in WSL or Ubuntu VM.

Also, be sure you have X11 libraries installed there. Pretty sure WSL doesn't have the X11 capabilities and maybe your Ubuntu VM has not installed the libx11-dev package

alefnull commented 5 months ago

It's expected ctrl+c to not work, because ruscii puts the terminal in something called "raw mode", where input keys are not interpreted as usual. Nevertheless, the configured keys should work... 🤔

ah right, of course. forgot about raw mode.

Also, be sure you have X11 libraries installed there. Pretty sure WSL doesn't have the X11 capabilities and maybe your Ubuntu VM has not installed the libx11-dev package

yeah, i had to fiddle around with the x11 requirement a couple times already after being confused by the build errors, like "where on earth am i using x11 in here?" 😆

in all honesty, as much as i like ruscii and have enjoyed playing with it, i started experimenting last night with trying to recreate dvd-term using only crossterm, and it's significantly easier than i thought, with at least one or two bonus advantages (like being able to leave the background color "clear" instead of opaque, to allow transparent terminals to display transparently while the logo bounces around. (this is something i couldn't figure out how to do in ruscii, if it's possible)

i haven't made any concrete decisions, but it's at least seeming somewhat likely at this point that i may just end up rewriting the whole thing to use crossterm directly. they do in fact have key release events now, which also seems to make device_query a bit redundant at this point. so i may just drop the unnecessary dependencies.

genuinely sorry to have revived an old issue just to come back and say "yeah i might stop using your project soon" 😢. just to reiterate - ruscii is awesome and i will continue to have fun with it in other ways, regardless of what i do with dvd-term. 😛

fadeevab commented 5 months ago

👋 Hey, an author of this issue here! :) I had a similar experience ending up with crossterm + loop (or such). If ruscii had been implemented via crossterm it would've got more "traction" as a tool for a quick start with game loops :)

alefnull commented 5 months ago

👋 Hey, an author of this issue here! :) I had a similar experience ending up with crossterm + loop (or such). If ruscii had been implemented via crossterm it would've got more "traction" as a tool for a quick start with game loops :)

honestly, i may even still take a crack at making a pull request here to either add a feature flag to just use crossterm's built-in input handling, or any other solution i can come up with. it seems to me that at the time of ruscii's creation there was a valid reason to use the approach they went with, but since crossterm has since been continually updated and now even offers key release events and more, it seems like it would be very beneficial to update ruscii with a way to take advantage of that while lowering the number of required dependencies which is always a good thing! 😄

lemunozm commented 5 months ago

No worries at all @alefnull. The selling point of ruscii is that it gives you release events. If you do not need those, I would also use crossterm directly.

ruscii is actually implemented using crossbeam but, as @alefnull says:

it seems to me that at the time of ruscii's creation there was a valid reason to use the approach they went with

That's is true. At the time of ruscii implementation crossterm didn't support release events. Nevertheless, AFAIK, not all terminals have implemented that new feature. So if you implement your app using them, it could not work for all your users.

it would be very beneficial to update ruscii with a way to take advantage of that while lowering the number of required dependencies which is always a good thing! 😄

That would be awesome. Right now, I'm in maintenance mode, but I would be happy to review and support any PR if anyone wants to tackle it.

Probably it can be as simple as making the Keyboard struct to be a trait that will be implemented by two types (names can vary):

Can even be included in the crate under a feature flag to avoid fetching 3party dependencies