[AL5] Unichar is always NULL when I get a key up
jmasterx

When I get a key down, the unichar is what it is supposed to be, but when I get a key up, unichar is 0. The only thing that has stuff in it is the keycode. Is this normal? If so, how can I get the unichar to get the same value on keyup as on keydown?

Thanks

Using AL5 4.9.22

#SelectExpand
1AguiKeyboard AguiAllegro5EventManager::createKeyboard( 2 ALLEGRO_KEYBOARD_EVENT *event ) 3{ 4 ALLEGRO_KEYBOARD_STATE st; 5 al_get_keyboard_state(&st); 6 7 AguiKeyEnum key = KeyNone; 8 if(event->unichar < 128) 9 { 10 key = (AguiKeyEnum)event->unichar; 11 } 12 13 if(event->keycode == ALLEGRO_KEY_DELETE) 14 { 15 key = KeyDelete; 16 } 17 18 return AguiKeyboard(key,getExtendedKey(event->keycode), 19 event->keycode,event->modifiers,event->unichar,event->timestamp, 20 al_key_down(&st,ALLEGRO_KEY_ALT), 21 al_key_down(&st,ALLEGRO_KEY_LSHIFT) 22 | al_key_down(&st,ALLEGRO_KEY_RSHIFT), 23 al_key_down(&st,ALLEGRO_KEY_LCTRL) 24 | al_key_down(&st,ALLEGRO_KEY_RCTRL)); 25 26}

Matthew Leverton

It's only available in key down:

http://www.allegro.cc/forums/thread/604432/872027#target

There really should be something like a KEY_PRESS event that represents a completed unichar sequence, while KEY_DOWN/UP only represent single keys.

jmasterx

Is it then a good idea to store the keyDown data and reuse on keyUp or is that bad practice?

Karadoc ~~

If you need the unichar data for your handling of key up events, then I suppose storing it from the key down event is the only possible way. But I'm not sure why you'd want the unicode data for key up anyway. Usually unicode is only useful for entering text, and it is conventional to have the text entered on the key down event rather than key up. For controls in a game or such, it's probably best to just use the keycode.

By the way, the post Matthew linked to describes an example that clearly demonstrates the problem with associating unichar with key down (or key up) events. It's worth reading.

Trezker

Wait, so things could go wrong having unichar coming from KEY_DOWN to, as described in the post Matthew linked to. Isn't this a bit of a flaw in A5?

I guess a KEY_CHAR event could be added.

Thomas Fjellstrom

It sounds like if you have deadkeys or some kind of input method driver setup, things could get funky, it may give you multiple keydown's for a single wanted character. I'm not sure about that, but people have said it does seem possible.

Elias

Yes, as that post says, we kinda agreed that KEY_CHAR would be the better solution but it was too big a change to make before 5.0. There really isn't a problem though with KEY_DOWN, it's just KEY_DOWN and KEY_CHAR rolled into one. If .unichar is 0 you know that it's a dead key (so you completely ignore it for text input - but still use the keycode for things like when you're configuring game key bindings) and if .keycode is 0 (not sure this can ever happen right now) it would be a key only relevant to text input.

Michał Cichoń

If that was too late for 5.0, how about 5.1?

Elias

Yes, for 5.1 I'd say we add a KEY_CHAR and only produce KEY_DOWN when a physical key is pressed.

We also need better support for multiple mice and multiple keyboards and other input devices, so likely there's another event or two we'll have to add.

Thomas Fjellstrom

Don't forget multi touch, which isn't the same as multiple input devices.

Elias

Well, multi touch is easy, just need an .id field in the mouse events. Or maybe make separate TOUCH_BEGIN, TOUCH_MOVE, TOUCH_END events instead of using BUTTON_DOWN, MOUSE_AXES, BUTTON_UP.

Thomas Fjellstrom
Elias said:

Well, multi touch is easy, just need an .id field in the mouse events.

I don't think its that simple. It seems everyone doing multitouch has went with special events for multitouch due to special requirements mt has. You might want to have a look at iOS's mt events, XI2's mt events, and maybe even the linux kernel's mt events.

Elias

Hm, googling for XI2 seems to suggest the opposite. E.g. http://cgit.freedesktop.org/xorg/proto/inputproto/tree/XI2proto.txt says:

Quote:

An XIDeviceEvent is generated whenever the logical state of a device
changes in response to a button press, a button release, a motion, a key
press or a key release. The event type may be one of KeyPress,
KeyRelease, ButtonPress, ButtonRelease, Motion.

So they have the same event now not only for button and touch but even for motion and keyboard keys.

ios also is a special case as there is no mouse. If there was a pointing device for ios most likely it would be reported with TOUCH_BEGIN/TOUCH_END.

Matthew Leverton
Elias said:

Yes, for 5.1 I'd say we add a KEY_CHAR and only produce KEY_DOWN when a physical key is pressed.

That could break existing programs. How hard would it just be to do something like?:

if (unichar) {
  send(ALLEGRO_EVENT_KEY_UNICHAR);
}

Then on the KEY_DOWN event, always set unichar to 0. For Allegro 5.2, perhaps a more robust unichar system could be implemented, but it seems like doing it this way would prevent potential backward compatibility problems and shouldn't be any worse than the current implementation.

jmasterx

Yea I agree

Michał Cichoń

I think KEY_CHAR may be introduced in 5.1, while config determine if old behavior is required or not. That way Allegro will be improved and backward compatibility will be keep by config. In 5.1 mixed message should be deprecated and removed in 5.2. IMHO

In case of iPad etc multitouch is major input system, therefore they may it directly into virtual keyboard. How about Windows or Linux with multitouch screen? You can still have mouse and use multitouch. TOUCH_BEGIN, TOUCH_MOVE and TOUCH_END seems reasonable to me. If user want, he/she may connect them with MOUSE_UP/DOWN/MOVE.

Thomas Fjellstrom

In 5.1 mixed message should be deprecated and removed in 5.2. IMHO

Odd minor version numbers are used exclusively for WIP releases. 5.2 will be the next stable release.

Michał Cichoń

Forgot about that, but still. WIP is good place for changes IMHO.

Matthew Leverton

My point is simply that if we are acknowledging that the current system is "broken," and likely to change, we can minimize backward compatibility (at the source level) problems by introducing a UNICHAR event now and removing the unichar from the KEY_DOWN event.

Even if KEY_DOWN still produces extraneous events and UNICHAR isn't entirely perfect in 5.0, we would be no worse off than we currently are.

It would also minimize the complaints and confusion over why KEY_UP doesn't have unichar.

jmasterx

I agree

Goalie Ca

I'm thinking so too. It's easier to deal with a small bug than design around false assumptions.

Peter Wang

I suppose it won't be too big of a change for users to deal with, on a par with making pre-multiplied alpha the default.

edit: in fact, KEY_CHAR might be exactly like KEY_REPEAT

Attached a patch for SVN (untested on Mac). I think most people are in agreement that this should go in 5.0?

Matthew Leverton

KEY_CHAR might be exactly like KEY_REPEAT

It might be useful to know if it came from a repeat. This is probably an abuse of terminology, but keyboard.modifiers & ALLEGRO_KEYMOD_REPEAT would be sufficient.

However, even if that's not possible, I agree that KEY_REPEAT is not necessary.

Peter Wang

I'm not sure if we should reuse the modifiers field or add a new field, but it's easy either way.

torhu

I'm a bit confused as to the difference between ALLEGRO_EVENT_KEY_DOWN and ALLEGRO_EVENT_KEY_CHAR. If I type the letter 'ö', I get two KEY_DOWNs, but I also get two KEY_CHARs, even though the '¨' is on a 'dead' key. The first KEY_CHAR has a zero unichar field, the second contains the correct, complete letter.

If I type 'é', I get four KEY_CHARs, last one contains 'é' in the unichar fields. This is the output of the ex_keyboard_events example (console set to UTF-8):

KEY_DOWN  code=217, char=' ' (   0), modifiers=00000000, [LCTRL]
KEY_CHAR  code=217, char=' ' (   0), modifiers=00000002, [LCTRL]
KEY_DOWN  code=220, char=' ' (   0), modifiers=00000000, [ALTGR]
KEY_CHAR  code=220, char=' ' (   0), modifiers=00000042, [ALTGR]
KEY_DOWN  code=065, char=' ' (   0), modifiers=00000000, [KEY65]
KEY_CHAR  code=065, char=' ' (   0), modifiers=00000042, [KEY65]
KEY_UP    code=065, char=' ' (   0), modifiers=00000000, [KEY65]
KEY_UP    code=217, char=' ' (   0), modifiers=00000000, [LCTRL]
KEY_UP    code=220, char=' ' (   0), modifiers=00000000, [ALTGR]
KEY_DOWN  code=005, char=' ' (   0), modifiers=00000000, [E]
KEY_CHAR  code=005, char='é' ( 233), modifiers=00000000, [E]
KEY_UP    code=005, char=' ' (   0), modifiers=00000000, [E]

The sequence of keys pressed on my Norwegian keyboard is AltGr+\, and then E.

The docs for ALLEGRO_EVENT_KEY_CHAR say that "A character was typed on the keyboard, or a character was auto-repeated". But in reality, KEY_CHAR is a superset of KEY_DOWN, and you always get both events. Maybe this isn't a problem, but it strikes me as odd.

Elias

I think no KEY_CHAR should be posted for the modifier keys.

Matthew Leverton

I think it should look like:

KEY_DOWN  code=217, char=' ' (   0), modifiers=00000000, [LCTRL]
KEY_DOWN  code=220, char=' ' (   0), modifiers=00000000, [ALTGR]
KEY_DOWN  code=065, char=' ' (   0), modifiers=00000000, [KEY65]
KEY_UP    code=065, char=' ' (   0), modifiers=00000000, [KEY65]
KEY_UP    code=217, char=' ' (   0), modifiers=00000000, [LCTRL]
KEY_UP    code=220, char=' ' (   0), modifiers=00000000, [ALTGR]
KEY_DOWN  code=005, char=' ' (   0), modifiers=00000000, [E]
KEY_CHAR  code=005, char='é' ( 233), modifiers=00000000, [E]
KEY_UP    code=005, char=' ' (   0), modifiers=00000000, [E]

Peter Wang

Oops, modifier keys should not send CHAR events. How is this patch? (untested on OS X)

I set my keyboard layout to Norwegian on Windows XP, and pressed AltGr+e and got:

KEY_DOWN  code=217, char=' ' (   0), modifiers=00000000, [LCTRL]
KEY_DOWN  code=220, char=' ' (   0), modifiers=00000000, [ALTGR]
KEY_DOWN  code=005, char=' ' (   0), modifiers=00000000, [E]
KEY_CHAR  code=005, char='€' (8364), modifiers=00000042, [E]
KEY_UP    code=005, char=' ' (   0), modifiers=00000000, [E]
KEY_UP    code=217, char=' ' (   0), modifiers=00000000, [LCTRL]
KEY_UP    code=220, char=' ' (   0), modifiers=00000000, [ALTGR]

torhu

Looks good to me - haven't tested the patch, though. I don't know why AltGr sends an LCTRL event, but maybe it's Windows that does that.

BAF

I was going to suggest modeling it after the way .NET does it, but what Peter Wang has posted is exactly that. I assume Matthew's example matches that as well.

Trezker

I have this code now for inserting a char in ustr. Anything wrong with this?
I noted that if I hold altgr and keep pressing a letter, cursor only moves half the time, why?
The font doesn't support the character that comes out so I just get boxes for this. Recommend a font that has all these symbols?

I do convert to c string before drawing, perhaps this is why things get screwed up?

int pos = al_ustr_offset(text, cursor);
if(al_ustr_insert_chr(text, pos, event.keyboard.unichar)>0)
{
   ++cursor;
   Push_event(Event(this, "changed"));
}

Peter Wang

Looks okay. You might want to compare with TextEntry::on_key_down() in nihgui.cpp.

torhu

I've made a patch that skips sending KEY_CHAR events for dead keys. It also sends two char events when that's appropriate. The output of ex_keyboard_events now matches Matthew's 'é' example. Here are some other examples:

'¨', 'o' to get 'ö':

KEY_DOWN  code=068, char=' ' (   0), modifiers=00000000, [KEY68]
KEY_UP    code=068, char=' ' (   0), modifiers=00000000, [KEY68]
KEY_DOWN  code=015, char=' ' (   0), modifiers=00000000, [O]
KEY_CHAR  code=015, char='ö' ( 246), modifiers=00000000, [O]
KEY_UP    code=015, char=' ' (   0), modifiers=00000000, [O]

'¨', 'k', which is an invalid combination, and produces two characters:

KEY_DOWN  code=068, char=' ' (   0), modifiers=00000000, [KEY68]
KEY_UP    code=068, char=' ' (   0), modifiers=00000000, [KEY68]
KEY_DOWN  code=011, char=' ' (   0), modifiers=00000000, [K]
KEY_CHAR  code=011, char='¨' ( 168), modifiers=00000000, [K]
KEY_CHAR  code=011, char='k' ( 107), modifiers=00000000, [K]
KEY_UP    code=011, char=' ' (   0), modifiers=00000000, [K]

'¨', space, to get just the accent:

KEY_DOWN  code=068, char=' ' (   0), modifiers=00000000, [KEY68]
KEY_UP    code=068, char=' ' (   0), modifiers=00000000, [KEY68]
KEY_DOWN  code=075, char=' ' (   0), modifiers=00000000, [SPACE]
KEY_CHAR  code=075, char='¨' ( 168), modifiers=00000000, [SPACE]
KEY_UP    code=075, char=' ' (   0), modifiers=00000000, [SPACE]

Maybe sending two char events for invalid combinations is a bit over the top, but that's how Windows does it.

I don't know why Allegro doesn't use the WM_CHAR messages, but that might be a better fix than checking the return value of ToUnicode to detect dead keys, like I did.

Peter Wang

That looks better, thanks. I will commit it, with an analogous change for X11.

Can someone update OS X?

Evert

I'm not entirely clear on what the problem is. It seems to have something to do with dead keys, which doesn't quite seem to work the same way on OS X.
I can do "option-e" and the system will wait for me to type another character (say e or k) at which point I will either get é or ´k. In ex_keyboard_events I get CHAR events for "ALT" (with an invalid character code, more on that next) and for "e" and "k", but I don't get character events for é (rather than e) or ´.

I also get "ex_keyboard_events[11907:903] *** -[NSCFString characterAtIndex:]: Range or index out of bounds", which is due to Allegro's keyboard driver asking for the character corresponding to the "ALT" up/down events.

Now, some or all of this is probably due to the way Allegro interprets OS X keyboard events. I can look into it, but I can't give a reliable estimate for when I can do that; it depends on how smoothly some other things I have to do go.

Peter Wang

The KEY_CHAR event should not be generated for modifier keys (shift, alt, ctrl, etc.), nor for dead keys.

_al_osx_keyboard_handler in keybd.m has this line:

const char upper_character = [[event characters] characterAtIndex: 0];

What it probably should be doing is generating a KEY_CHAR event for each character returned by [event characters]. I think this is the source of the problems you mentioned.

Evert

What it probably should be doing is generating a KEY_CHAR event for each character returned by [event characters].

Makes sense.

Quote:

I think this is the source of the problems you mentioned.

Yes, I'm sure it is. Actually, there are two calls to characterAtIndex at that point in the code, and two lines of output complaining about it.

Thread #605801. Printed from Allegro.cc