[SDL] RFC: prototype implementation of physical key codes

Christian Walther cwalther at gmx.ch
Sun Sep 3 04:03:13 PDT 2006

So, at <http://bugzilla.libsdl.org/show_bug.cgi?id=319> is the thing 
I've been talking about for a while: a prototype implementation (for Mac 
OS X (Quartz) and X11) of a keyboard handling feature that in my opinion 
could replace both the "sym" field of the SDL_keysym structure 
(SDL_Event.key.keysym) with the associated SDLK_* constants and its 
"scancode" field. However, since I've gotten the impression that some 
people are of different opinion, I'm proposing it as an addition rather 
than a replacement.

It is implemented as a patch against SDL 1.2 (rev. 2741 from today, but 
none of the affected files has changed after rev. 2549) because at the 
time I started it, SDL 1.3 wasn't functional enough for it, but the 
intention is to get it into SDL 1.3 if people agree.

It adds three things to the SDL API:

- A new field in the SDL_keysym (SDL_Event.key.keysym) structure: 
SDLPKey pkey.

- An enumerated type SDLPKey in SDL_keysym.h with a set of constants for 
this field: e.g. SDL_PK_A, SDL_PK_RETURN, SDL_PK_LSHIFT.

- A new function: const char * SDL_PKeyName(SDLPKey pkey), explained below.

Unlike the SDL_Event.key.keysym.sym field with its SDLK_* constants, 
which refers to a key with a particular label, the 
SDL_Event.key.keysym.pkey field with its SDL_PK_* constants refers to a 
key at a specific physical position on the keyboard (hence the name 
"physical key code"). E.g. SDL_PK_A means "the leftmost letter key in 
the middle alphabetic row" (which is labeled "A" on a US keyboard).

The SDL_PKeyName function takes a physical key code and returns a 
human-readable description for that key that ideally matches what's 
printed on the key cap on the user's keyboard, i.e. it takes into 
account the OS' current key mapping settings.

One case where the usefulness of such a system should be obvious is 
emulators (of devices with PC-like keyboards, e.g. Basilisk or Qemu or 
PearPC) - what they usually did up to now was to work with the 
platform-dependent "scancode" field and translate it to the emulated 
scancodes they need using platform-specific lookup tables. Now SDL takes 
the work of compiling these tables off them.

However, even in the case of games I think this system has its 
advantages. First, when the keyboard is used as some sort of gamepad, it 
seems much more natural to map the keys by their position than by their 
label. E.g. SDL_PK_Z will always be below SDL_PK_A, while SDLK_z is only 
below SDLK_a on a US keyboard, not on a French or German one. Second, I 
find that SDL_PKeyName() works much better for presenting key names to 
the user than SDL_KeyName() - e.g. when I press the "ö" key on my Swiss 
German keyboard, the latter will say something like "world 86", while 
the former says "ö".

(And, just for completeness, I should mention that the pkey field is 
*just as useless* as the sym field for text input. To do text input, use 
the unicode field or SDL 1.3's text input events.)

So, I'd like to hear some feedback about this. In particular, three 

- Do you think such a feature would be useful to have in SDL 1.3?

- Does it work for you? I'm particularly interested in keyboards other 
than the standard 104/105-key ISO/ANSI Mac and PC keyboards I have here. 
You can test it using the SDL/test/checkkeys.c which I've updated to 
also show the physical key codes and the names determined by 
SDL_PKeyName(). In addition, the pkeydemo.c attached to the bugzilla 
entry is a small example of how I expect this to be used in a game. Try 
it with different keyboard mapping settings and observe how (hopefully) 
1. the default keys stay in sensible positions (e.g. the "left" key will 
always be to the left of the "right" key) and 2. the keys are presented 
using their correct labels.

- What do you think about the naming of functions, constants and 
everything? The names I picked are pretty arbitrary and I'm open to 
suggestions for better names.

What's still missing:

- Implementations for other backends, most importantly on Windows. I 
could try to do this, but we would probably have a result of better 
quality in less time if someone with more experience (and interest) in 
Windows programming than I would do it.

- The X11 implementation needs X-server-specific lookup tables to work 
properly and falls back to mapping-by-keysym if none of the included 
ones fits. At the moment, only tables for Linux and Mac OS X are 
included (and the former is incomplete, too) - more will probably be needed.

And a few more notes:

- When an unknown key is pressed or when the X server's key codes are 
unknown, a message is printed to stderr. These pieces of code are 
bracketed by #if 1 ... #endif and I'm unsure if they should be enabled 
in a release binary. Any opinions?

- The names returned by SDL_PKeyName() (for keys like "return", "space", 
"command") are English, not localized. I'm not sure if there's a 
sensible way around this. For now, the burden of localizing them (at 
least a few known ones, since SDL_PKeyName() can return anything) is on 
the application developer.

- In the Cocoa implementation, mostly out of laziness, I'm 
short-circuiting the complicated handling of modifier keys and instead 
handle them like the other keys, just in response to NSFlagsChanged 
events. It seems that the complicated system was partly there from the 
beginning, partly introduced in rev. 1241 to fix the problem of 
incorrect modifier states when switching to or away from the application 
with modifier keys pressed, and later expanded in rev. 1394. However, 
that problem doesn't seem to resurface now with my simplified solution. 
This needs some more careful examination, but it seems possible to me 
that the complicated system could be removed entirely.


More information about the SDL mailing list