Mapping of key codes

Little question. Using https://www.haiku-os.org/docs/api/keyboard.html I’m trying to figure out what key-codes are usable and what mapping they have. get_key_map tells me about the mapping but I’m looking also for something like XDisplayKeycodes which returns the minimum and maximum key codes a device uses. Basically I want to build a list of all usable key codes indexed from 0 to the maximum. But I can’t figure out how I know the key code range. I only see in key_map an array of max 128 entries. Is the range 0 to 127 then? Or can I find it somewhere?

keycode is a uint32, anything can come in this range. They are maximum 128 mappings (1-128). For unmapped keycodes, B_UNMAPPED_KEY_DOWN/B_UNMAPPED_KEY_UP messages are sent.

see
https://git.haiku-os.org/haiku/tree/src/add-ons/input_server/devices/keyboard/KeyboardInputDevice.cpp#n438
and
https://git.haiku-os.org/haiku/tree/src/kits/shared/Keymap.cpp#n346

From the code I read that it is not possible yet in haiku to determine the key-code range of the attached device. The only limits I see in the code are:

if (keycode == 0)
continue;

and

if (keycode < 256) {
}

Thus I have to assume keyboard under haiku has 255 keys (range 1-255). That’s acceptable. X11 reports a range of 9-246 inclusive.

Now this check is maybe wrong, because the relevant “states” array is 128 bits length, likely difficult to toggle any bit over 128.

So this means the actual key-code range in haiku is 1-127 inclusive. That’s interesting.

The mapped key-code range is 1-128.

I tried getting get_key_map to work but I’m running into troubles including SEGF.

One problem I have is how this B_FUNCTION and B_F#_KEY work. They overlap with other key definitions so I assume there is a special math logic in here I dont see?

Second is the segfault. From the documentation I understand it should be like this:

get_key_map(&kmap, &kbuf);
if(kmap->normal[something] >= 0){
   const char *const charBegin = kbuf + kmap->normal_map[something];
   const int charLen = *charBegin;
   utf8Char = new char[charLen+1];
   strncpy(utf8Char, charBegin+1, charLen);
   utf8Char[charLen] = 0;
}

But this segfaults somewhere. If I get this right then the normal_map[*] points into the kbuf (byte offset). The first byte at this location is the number of characters. Following the number of characters. Did I get something wrong?

The function keys are a bit annoying. The character reported is B_FUNCTION_KEY, for all of them. Basically, it means “not a character”. And then you have to look at the key code to identify them. More details; https://www.haiku-os.org/legacy-docs/bebook/TheKeyboard_CharacterConstants.html

You may find more info about get_key_map in the Be Book: https://www.haiku-os.org/legacy-docs/bebook/TheInputServer_Functions.html#get_key_map

I’m sorry to say this but this document doesn’t make any sense. I’m not understanding “how” one is supposed to use it. The text is confusing and contradictory, which is why I ask here.

Let’s take the following situation:
for(int i=0; i<128; i++){…}

we iterate over all… what? the key-code? key-something-code? key scan-code? I get the impression the key_map (for example normal_map) is indexed by “key-code” but I’m not sure.

The document talks about “key-code”, “key” and “character” but mixes them up permanently. Sometimes it talks about “key-code” and compares it to B_RETURN for example (this is what I get is correct). Then again it talks about “key” and compares it to something similar. Then suddenly it talks about “character” and compares it… against the same constants. It’s a mess. I need a “clear” definition what the hell is going on and I’m really stuck here.

So:

  1. What is the “index” into key_map.normal_map? key-code? character? something else?
  2. Why is keybuffer[key_map.normal_map[i]] == 0? should this not be the length?
  3. What is B_RETURN and company? key-code or character?

What I got so far is that:

  1. codes in key events seem to match B_RETURN and company
  2. key_map.normal_map points to 0-length strings all the time (seems wrong to me)
  3. codes in key events seem to match B_FUNCTION_KEY not B_F1_KEY. but does this not contradict (1)?

I solved the problem now with a bunch of switch() tables and some dirtiness but at last I can identify now most keys. Some are still empty-string so some kind of special keys haiku has no mappings for. For a user this is though in the end not too bad since input-binding works by pressing the key you want to bind. If the name is cryptic this is foul but not a show-stopper.

For future users I suggest to improve the key-handling. It’s spread over different places making it hard to get working, especially with the documentation as it stands right now. There should be 1 key-code property which uniquely identifies keys on the device. If it is desired to keep the split property system it would be better to rename the constants with prefixes to make it clear which constant group they belong to, aka are they for key-code-1 or key-code-2 to avoid this head-ache of confusion. Could be even new constants pointing to the old ones but with meaningful and clear names.

It is one place where we have to live with BeOS legacy decisions, at least until R2.

There are only two sets of codes. Let’s make up names for them since the documentation doesn’t really do that.
On one side (input) there are “key codes”. They number the keys on the keyboard mostly from top left to bottom right (with some keys out of place as they were added later).

On the other side (output) of the keymap, there are “characters”. These are unicode characters, except for B_FUNCTION_KEY. B_ENTER, B_BACKSPACE, etc are in this space (they are in fact mapped to the ASCII control characters - also part of Unicode).

B_F1_KEY to B_F12_KEY, and in general all the B_*_KEY constants, are key codes. As a result it is not possible to remap function keys using the keymap.

Key codes are in the range 0 to 127, with 0 to 0x6A actually used and some space left for extra keys (if you are the owner of a keyboard with 24 function keys, for example). They are always mapped to the same physical key.

Characters are… well, characters, and the user can customize their keymap and use anything they want from the whole unicode space.

So, if you are after physical key positions, you use key codes. Otherwise, you use characters from the keymap.

2 Likes