Skip to content

getKeyState bug #45

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

Open
MatthewZ0823 opened this issue May 25, 2025 · 0 comments
Open

getKeyState bug #45

MatthewZ0823 opened this issue May 25, 2025 · 0 comments

Comments

@MatthewZ0823
Copy link

There is a bug in the implementation of the keyCheckerFunction in src/GraphicSVG/App.elm which causes certain keys like the "," or "." to not be able to be registered in a game app. For example in the following elm program (fork link)

myShapes model =
  [
    model.buttonPressed
      |> Debug.toString
      |> text
      |> centered
      |> filled black
  ]

type Msg = Tick Float GetKeyState

type alias Model = 
  { time : Float 
  , buttonPressed : String
  }

update msg model = 
  case msg of
    Tick t (getKeyState, _, _) -> 
      { time = t 
      , buttonPressed = getKeyState (Key ",") |> Debug.toString
      }

init = { time = 0, buttonPressed = "" }

main = gameApp Tick { model = init, view = view, update = update, title = "Game Slot" }

view model = collage 192 128 (myShapes model)

The text in the center does not change to "Down" when the comma key is pressed, which is unintended behavior.

This is because the game app subscribes to key events on the document as follows:

-- One line 89 of src/GraphicSVG/App.elm
subs : List (Sub (HiddenMsg userMsg))
subs =
    [ onKeyUp (D.map KeyUp (D.field "keyCode" D.int))
    , onKeyDown (D.map KeyDown (D.field "keyCode" D.int))
    , ...
    ]

When a key is pressed down, the onKeyDown subscription fires and sends a KeyDown message with the keyCode of the button pressed. The KeyDown message is then handled by the hiddenGameUpdate function. Where the keyCode of the button pressed is added to the list of keys in the hiddenModel. hiddenModel.keys keeps track of a list of keys and their pressed state.

        -- In the hiddenGameUpdate function on line 699 of src/GraphicSVG/App.elm
        KeyDown keyCode ->
            ( ( userModel, { hiddenModel | keys = insertKeyDict hiddenModel.keys keyCode WentDown } ), Cmd.none )
        KeyUp keyCode ->
            ( ( userModel, { hiddenModel | keys = insertKeyDict hiddenModel.keys keyCode WentUp } ), Cmd.none )

Then when a user wants to query if a key is being pressed, the keyCheckerFunction function is invoked with the hiddenModel.keys being passed into the dict param:

-- On line 233 of src/GraphicSVG/App.elm
keyCheckerFunction : Dict.Dict Int ( KeyState, a ) -> Keys -> KeyState
keyCheckerFunction dict key =
    let
        state =
            Dict.get kc dict

        kc =
            case key of
                Key str ->
                    Char.toCode <|
                        Char.toUpper <|
                            case String.uncons str of
                                Just ( a, _ ) ->
                                    a
                                Nothing ->
                                    'z'

                Backspace ->
                    8

                ... -- Imagine other special characters below
    in
    case state of
        Just ( JustDown, _ ) ->
            JustDown
        Just ( Down, _ ) ->
            Down
        Just ( JustUp, _ ) ->
            JustUp
        Just ( Up, _ ) ->
            Up
        Nothing ->
            Up

So in our sample program at the start of this bug report, when we query to see the state of Keys ",", the keyCheckerFunction gets the unicode code of the "," character, and then checks in the hiddenModel.keys to see its state.

The problem is that when the comma key is pressed, the onKeyDown subscription puts the Javascript Keycode of the "," button as the key in the hiddenModel.keys dictionary, but the keyCheckerFunction is looking for the Unicode Code of "," as the key. The Javascript KeyCode of a button may be different then its Unicode Code, as is the case with the comma button. This causes the keyCheckerFunction to not find anything in the hiddenModel.keys dictionary, concluding that the button must not be pressed down.

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

No branches or pull requests

1 participant