ohanhi / keyboard-extra

Nice handling for keyboard inputs in Elm
http://package.elm-lang.org/packages/ohanhi/keyboard-extra/latest
BSD 3-Clause "New" or "Revised" License
49 stars 13 forks source link

Keys are not released under certain circumstances #6

Open manuscrypt opened 8 years ago

manuscrypt commented 8 years ago

Hi

When I press e.g. "F1" in Chrome, or "Ctrl+F" in Firefox, this will trigger the browser-related command (help and search, respectively).

When returning to the browser, the "F1" is not being released in the first case, "Ctrl" in the second.

The effect is in short: There are "pressed" keys showing, when there aren't any keys pressed. This can also be reproduced by hitting multiple keys (arrows and others mixed)

ohanhi commented 8 years ago

Yes, this is caused by the browser not sending keyup events in those occasions. I guess I'll have to think about this some more.

xpe commented 8 years ago

I've also noticed this kind of thing happening when pressing "Cmd +", "Cmd -", or "Cmd 0" to change fonts in the browser.

ohanhi commented 7 years ago

There seems to be no real way to solve this with the approach I've taken in keyboard-extra, since the keyup event simply doesn't fire. :disappointed:

ohanhi commented 7 years ago

Reopening just to show folks the issue is still there.

manuscrypt commented 7 years ago

What if there was a simple way to manually release all (or some) keys? (maybe there already is?). That might be helpful as a workaround in some situations.

ohanhi commented 7 years ago

Yeah, that we could do. That would only affect the isPressed/pressedDown, and not the subscriptions etc. But I guess it'd be better than nothing.

gregziegan commented 7 years ago

Also having this issue when I'm trying to implement undo/redo Cmd+Shift+Z and Cmd+Z. I'd be in favor of having some function to manually release as a stop gap solution

ohanhi commented 7 years ago

@manuscrypt and @thebritican: As a matter of fact, you should be able to do this already simply by replacing the Keyboard.Extra State with initialState in your update.

gregziegan commented 7 years ago

I've tried that 😢, but it means that the user has to release all the keys and press them all again.

Example, on the KeyDown subscription:

Keyboard.Extra.CharZ ->
  if isPressed Shift keyboardState && isPressed Control keyboardState then
     { model | edits = UndoList.redo model.edits, keyboardState = initialState }
  else if isPressed controlKey keyboardState then
     { model | edits = UndoList.undo model.edits, keyboardState = initialState }
  else
    model
Keyboard.Extra.Control ->
  if isPressed Shift keyboardState && isPressed CharZ keyboardState then
     { model | edits = UndoList.redo model.edits, keyboardState = initialState }
  else if isPressed CharZ keyboardState then
     { model | edits = UndoList.undo model.edits, keyboardState = initialState }
  else
    model

If i was able to say:

Keyboard.Extra.CharZ ->
if isPressed Shift keyboardState && isPressed Control keyboardState then
     { model | edits = UndoList.redo model.edits, keyboardState = removeKey CharZ keyboardState }
...

Then, users could just tap z. That behavior is not ideal since holding z should initiate more keydowns.

It's not an SSCCE but you can see this at work here:

Without the state resets:

https://ellie-app.com/HHbVvk6bY9a1/6

With the state resets:

https://ellie-app.com/HHbVvk6bY9a1/7

Here's a debug file to just have a bunch of drawings on the screen to undo/redo: history-379.txt

ohanhi commented 7 years ago

Thanks for the thorough issue report and concrete usage example, Greg! I am just about to leave for a vacation, but I will come back to this.

ohanhi commented 7 years ago

@manuscrypt and @thebritican, a workaround has now been published with 2.1.0: forceRelease

mordrax commented 7 years ago

Hey @ohanhi i was just thinking of this from your docs:

Note When the user presses and holds a key, there will be many of these messages before the corresponding key up message.

And had an idea. Instead of relying on the browser to send keyup, can you check for the absence of repeated keydowns to change the state of the key after a while?

ohanhi commented 7 years ago

@mordrax Unfortunately that wouldn't work either, because the browser will only ever fire repeated keydowns for the last key introduced. So if you hold A down and start pressing B as well, B will keep firing keydowns and A will not.

jhbrown94 commented 6 years ago

forceRelease seems to be gone in the latest version of keyboard-extra -- is there a new workaround strategy? (Just emptying pressedKeys on the model?)

ohanhi commented 6 years ago

@jhbrown94 Yes, you can do whatever changes you like to the List Key in your model. My current suggestion would be to add a subscription port that sends in window blur events. I've detailed this idea here: https://github.com/ohanhi/keyboard/blob/master/src/Keyboard.elm#L37-L58