Handling dead keys in SDL

Discussion in 'Game Development (Technical)' started by ggambett, Jun 11, 2005.

  1. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    I have a problem with international keyboard input in SDL, in particular with the dead keys.

    I have Unicode translation enabled, so when I press the Ñ key (it's a separate key in my spanish keyboard), I get its Unicode number, which I then translate to UTF8 and everything works fine.

    My problem is with the characters that require two keypresses : to get the Ã￾ character, I press ' and then A. In every other program, nothing appears when I press ', and when I press A, an Ã￾ appears. That's how it should work. However, in SDL I'm getting two events, for ' and A in Unicode.

    I don't want to handle the dead keys myself (ie if I get an ' and then a vowel, substitute the character by hand), and I'm sure there must be a way to do this since SDL is used for several international apps... so... what's the secret?
     
  2. James C. Smith

    Moderator Original Member

    Joined:
    Aug 21, 2004
    Messages:
    1,768
    Likes Received:
    0
    I don’t know how DSL abstracts this stuff, but you may understand SDL better if you fist understand how Windows deals with this. There is a big difference between keys on your keyboard and the character they type. You need to use different API function (or respond to different messages) depending if you want to know about key events or character events. When I press the shift key I don’t get any character typed. When I press the 3/# key I either get a 3 character or a # character depending in if the shift key is being held down. When I press the G key I either get a G character or a g character depending on the state of the shift key and the caps lock.

    Keys generate up and down events. Your app can be notified when the G key goes down (WM_KEYDOWN) and when the G key goes up (WM_KEYUP). Games often use key events for actions like run, jump, move and shoot because they want to know if the key is being help and when it gets released. You should never use key events for input fields such as when a player types his name. Key messages to not include ASCII or UNICODE is for the keys. That comes later when a character is generated by the key. The keys are identified by SCAN codes or virtual key codes. There is not a separate scan code for the # key vs. the 3 key. That is a single key with a single scan code. Most keyboard have another key on the numeric keypad that can also type a 3 character. That 3 key has a different scan code than the 3 key at the top of the keyboard.

    Windows sends WM_CHAR messages when characters are typed. This is what you should respond to when someone is typing in a name. There is no such thing as a character being pressed and released. Characters get typed but not released. A character never goes "UP". This makes character messages bad for thing link run, jump, and duck. Characters are identified by ASCII codes or UNICODE. There is a different character code for 3 and #. But both 3 keys generate the same 3 character. There are not different character codes for the 3 typed on the numeric keyboard vs. the 3 typed at the top of the keyboard. The keys have different scan code, but the generate the same character.

    In the example you mentioned, windows will send WM_KEY up and down message for both of the keys pressed (’ and A) and also send a fifth message of type WM_CHAR to represent the Ã￾ character.

    If you want to know when a player types a Ã￾ character you should be responding to WM_CHAR messages (or the UNICODE equivalent). If you want to know when the ' KEY is pressed or released you need to be responding to WM_KEYxx messages and looking for virtual key codes or scan codes rather than ASCII or UNICODE. The ' key on your keyboard does not generate CHAR messages until another key is pressed but it does generate KEY up and KEY down messages. It's much like a shift key. It's not a dead key. It does generate KEY messages. It just doesn't type any chacaters just like the shift key doens't type characters.
     
    #2 James C. Smith, Jun 11, 2005
    Last edited: Jun 11, 2005
  3. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    I know that's how it works in Windows, I just don't know what's the equivalent in SDL, since SDL doesn't have separate messages for keypresses and chars :( And since the keypress event has a Unicode member, I think these events do the equivalent of TranslateMessage()... I don't know how to interpret it though.
     
  4. soniCron

    Indie Author

    Joined:
    May 4, 2005
    Messages:
    3,664
    Likes Received:
    0
    Is it possible you have to handle the dead keys yourself?
     
  5. Ryan Clark

    Indie Author

    Joined:
    Oct 29, 2004
    Messages:
    656
    Likes Received:
    0
    Just to make sure: Gabriel, you are using the unicode member of the SDL_keysym struct, right?

    If not, try that :)
     
  6. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    I hope not... I could do an ugly hack and handle the spanish keys... german and french keyboards are doable... but korean???

    Yes, I am. Do you do text inputs?
     
  7. mahlzeit

    Original Member

    Joined:
    Sep 26, 2004
    Messages:
    852
    Likes Received:
    1
    If SDL doesn't have a solution for this (maybe you can look through its source?), you can always override the message handler for the window and handle the proper Windows WM_CHAR events (or whatever) yourself. Of course, this isn't cross-platform, but at least it's something.
     
  8. Ryan Clark

    Indie Author

    Joined:
    Oct 29, 2004
    Messages:
    656
    Likes Received:
    0
    Yes, but our game doesn't currently support unicode. Someday we may, so I'd be interested if you do find a solution to this problem!

    Sounds like it's a flaw in SDL itself... as far as I know, there's no other method for obtaining char data from a keystroke.

    (Well, there's SDL_GetKeyName, but I think it will only report on the key pressed/released, ignoring modifiers.)
     
  9. James C. Smith

    Moderator Original Member

    Joined:
    Aug 21, 2004
    Messages:
    1,768
    Likes Received:
    0
    That sounds to me like a big flaw in the design SDL. I hope an SDL expert could come along and explain it for us. I seems very bad to me to shield the developer form the differences between key presses and the characters they generate. So in SDL, how can you tell if the shift key is down? Do they make up a fake UNICODE or ASCII value for shift?
     
  10. Ryan Clark

    Indie Author

    Joined:
    Oct 29, 2004
    Messages:
    656
    Likes Received:
    0
    Actually, I think SDL does work pretty similarly to the way Windows' WM_KEY/WM_CHAR system does. If you want the key up/down events, you look at the SDL_keysym's sym member. If you want the "char" value, you look at the SDL_keysym's unicode member (which is only defined on keydown events).

    I think the problem here is that the unicode result is broken for the non-standard "modifier" keys. As you can see here, the list of modifier keys is static... so, if your keyboard uses a modifier key that is not listed, I imagine that SDL will ignore it for the purposes of deciding the value of the unicode member. For standard modifiers, it works fine. (ie. If you press "SHIFT-A" the unicode member's value will be a capital "A".)
     
  11. James C. Smith

    Moderator Original Member

    Joined:
    Aug 21, 2004
    Messages:
    1,768
    Likes Received:
    0
    This is fine if you are trying to type an A but not fine if you are trying to use shift as your duck or jump key. My question was how can an game use SDL to see if the shift key was pressed.
     
  12. soniCron

    Indie Author

    Joined:
    May 4, 2005
    Messages:
    3,664
    Likes Received:
    0
    SDL_keysym's sym member reflects it.
     
  13. Ryan Clark

    Indie Author

    Joined:
    Oct 29, 2004
    Messages:
    656
    Likes Received:
    0
    Yep, soniCron is right. SDL_keysym's sym member is analogous to Windows' WM_KEY events.

    My SDL game uses arrow keys (which have no character representation), and the up/down sym values are exactly what I need.

    I think Gabriel's problem is a (smaller) flaw in SDL: The unicode value doesn't account for foreign "modifier" keys.
     
  14. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    Exactly. The SDL_KEYDOWN event has a lot of info (scan code, key symbol, modifiers, unicode translation), so you CAN know when the user presses the shift key without any problem. The problem is that the unicode translation apparently doesn't work as expected for foreign characters composed using dead keys. It works just fine for Ñ (U001F) which is a single key in my keyboard, but not for á or Ã￾, because of the dead key.
     
  15. John Rush

    Original Member

    Joined:
    Dec 21, 2004
    Messages:
    22
    Likes Received:
    0
    A quick search of the SDL source shows no signs of handling the WM_DEADCHAR message, which would be required to do what you want. It looks like a quick little hack in SDL_dibevents.c in DIB_HandleMessage() might do the trick.

    I think I can see how to code something that will work, but I can't test it as I have no dead keys on my keyboard. I suggest you have a look at the source and do something similar to the NO_GETKEYBOARDSTATE hack, but in the WM_KEYUP code -- and looking for WM_DEADCHAR, instead of WM_CHAR, course.

    Please let us know if you come up with a fix that works.
     
  16. Ryan Clark

    Indie Author

    Joined:
    Oct 29, 2004
    Messages:
    656
    Likes Received:
    0
    Remember: If you change the SDL source itself, you're going to have to redistribute that source with your program!

    If you submit your fix as a patch to the SDL project, hopefully they'll merge it into the next release... then there'll be no problem :)
     
  17. mahlzeit

    Original Member

    Joined:
    Sep 26, 2004
    Messages:
    852
    Likes Received:
    1
    You don't have to distribute the changed SDL sources with your program, but you do have to make them available for anyone who asks for it (possibly for a fee). If you don't want to go through the hassle of changing SDL, do what I suggested earlier: override the winproc of the SDL window, handle the WM_ events, and post an SDL event to the SDL loop in response. (I have sample code available if you want it, although it's not for WM_DEADCHAR.)
     
  18. soniCron

    Indie Author

    Joined:
    May 4, 2005
    Messages:
    3,664
    Likes Received:
    0
    Actually, I don't even think he'd need to go that far. He could post a link to the SDL website and a .diff of his changes, which should suffice. That said, the one problem with these suggestions is that he loses cross-platform compatability until his patch is accepted to the next SDL release (which would be months) and someone else writes code for Mac and Linux (which could be years even). I don't know if he's interested in cross-platform development, but if so, it won't help to have only Windows code that handles this. Of course, I have nothing to offer! ;)
     
  19. jetro

    Original Member

    Joined:
    Jan 21, 2005
    Messages:
    130
    Likes Received:
    0
    I just checked out with one of my games that my SDL event handling seems to correctly handle dead keys. I couldn't find anything really specific about it in the source, though.. and my bitmap font didn't really support much of the special chars. But for the few umlaut ones it has, the dead key method of entering them worked fine (i.e. press ¨ and then a resulted in ä).

    I noticed one thing in initialization though; it is probably pretty essential that you call SDL_EnableUNICODE(1); (and it probably has to be called after other SDL initialization). Other than that I just check in SDL_KEYDOWN SDL_Event processing that ctrl/alt are not pressed down and then event.key.keysym.unicode contains the char code.
     
  20. James C. Smith

    Moderator Original Member

    Joined:
    Aug 21, 2004
    Messages:
    1,768
    Likes Received:
    0
    So are you saying this ' key doesn't generate a WM_KEYDOWN and WM_KEYUP messages like a shift key would? I woun't expect it to generate any WM_CHAR message since it doen't type a character. To be honest, I am not familar with WM_DEADCHAR. I can understand why a WM_DEADCHAR message would be genrated rather than a normal WM_CHAR. But I don't understand why WM_KEYxx messages wouln't be generated or why you wouldn't use them if they are generated. According to the MSDN doecs, the WM_DEADCHAR is generated when a WM_KEYUP message is translated by the TranslateMessage function. So it seems the WM_KEYxx message are being generated. Isn't that what you should be resonding to?
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer