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
questions:
-
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)
- 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.-Christian