Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Windows: al_get_keyboard_state patch for 5.0.6 SVN

This thread is locked; no one can reply to it. rss feed Print
Windows: al_get_keyboard_state patch for 5.0.6 SVN
Dennis
Member #1,090
July 2003
avatar

UPDATE(June/24/2012): Ignore the patch in this thread.

[1] <- UPDATE(June/23/2012)#2 yet another update, also including additional primitives dependency for modified ex_keyboard_events in respective makelist file and also clearing the state on switching back in now to address an issue in wine

UPDATE(June/23/2012) new patch also addressing 'switch away, keys stuck in state' issue now as discussed in this thread

The attached files contain a refactoring for the Windows version of al_get_keyboard_state.

The only difference to the old version here is that in this new version the function always attempts to get the actual current keyboard state rather than returning a state which might not be up to date because it was filled/maintained asynchronously by windows system events.

Disclaimer: I haven't tested whether this new version is just as fast as the old one.
It's probably a bit slower, because it needs to convert the keyboard state from the Windows format to the internal Allegro format.

I have also attached a modified ex_keyboard_events.c which will display white lines based on synchronously read keyboard states in the main window.

credits to elias and zap0 who were most helpful while I hacked this up. :)

torhu
Member #2,727
September 2002
avatar

I think just clearing the keyboard state on switch out would be a good enough solution. I don't think that a key needs to register if you hold it down when switching to a program. Nobody would notice. Clearing the keyboard state on switch out fixes the real problem, which is that keys get 'stuck' if you switch out with keys held down. And the code to do that is much simpler.

I wish I had done this when was looking at the keyboard code a few months ago, but I got too busy. Sorry :-/

Some notes about the patch:

  1. It doesn't consider the extended keys. See the extkey_to_keycode and _al_win_kbd_handle_key_press functions.

  2. It duplicates the key state, the_state and the_real_state have the same purpose.

  3. VK_PAUSE is not an extended key, and doesn't belong in extkey_to_keycode.

But it is my opinion that just clearing the state is a 99% solution. I do that manually in my A5 game, and I'm not able to make it fail. In addition to clearing the state, it's a good idea to call update_toggle_modifiers() upon switch back in. The toggle modifiers (Num, Caps, and Scroll Lock) need to be in sync, since they have a persistent state. I can't remember exactly, but it's likely that you can then remove the update_toggle_modifiers call in _al_win_kbd_handle_key_press. And update_toggle_modifiers should probably be renamed to _al_win_kdb_update_toggle_modifiers if it's called from another file.

EDIT:
A more involved solution is to sync the keyboard state upon switch in, using the code you have already written. The rest of the needed code can be found at the beginning of the _al_win_kbd_handle_key_press function, where the key mapping happens.

Dennis
Member #1,090
July 2003
avatar

The original motivation for this patch was that ALLEGRO_KEY_PAUSE state differences could not be detected between two different states acquired by al_get_keyboard_state.

It turned out they still can't be detected because not even Windows can correctly read the keystate of that key (it generates a down and an immediate up event and no repeated down events even if it is kept depressed... so in other words it is impossible to determine whether it is currently being held down at a specific moment).

torhu said:

Some notes about the patch:

1. It doesn't consider the extended keys. See the extkey_to_keycode and _al_win_kbd_handle_key_press functions.
2. It duplicates the key state, the_state and the_real_state have the same purpose.
3. VK_PAUSE is not an extended key, and doesn't belong in extkey_to_keycode.

1. will check, thought the ALLEGRO_KEYBOARD_STATE did not have a field for modifier keys...at least I could not find one
2. elias and I agreed not to touch the_state because it is being used elsewhere as well and that patch was only supposed to improve behavior of programs using al_get_keyboard_state directly without affecting the current event system behavior (which seems to use the_state anytime to make updates based on windows system events)
3. ok

EDIT:
In addition to 2.) the windows api call to update the state can fail, so the_state is used as a fallback return value in case it's not possible to read the real most current state.

torhu
Member #2,727
September 2002
avatar

Dennis said:

The original motivation for this patch was that ALLEGRO_KEY_PAUSE state differences could not be detected between two different states acquired by al_get_keyboard_state.

Allegro 4 treats it as a toggle key, don't know if that's better or worse...

Quote:

It turned out they still can't be detected because not even Windows can correctly read the keystate of that key

Not even GetKeyState()? It doesn't always give the same result as GetKeyboardState().

Quote:

1. will check, thought the ALLEGRO_KEYBOARD_STATE did not have a field for modifier keys...at least I could not find one

Extended keys, not modifiers keys. Basically keys that didn't exist on early PC keyboards in the 80's. Like numpad Enter or the arrow keys.

Quote:

2. elias and I agreed not to touch the_state because it is being used elsewhere as well and that patch was only supposed to improve behavior of programs using al_get_keyboard_state directly without affecting the current event system behavior (which seems to use the_state anytime to make updates based on windows system events)

A quicker solution, but messier.

Quote:

In addition to 2.) the windows api call to update the state can fail, so the_state is used as a fallback return value in case it's not possible to read the real most current state.

Just don't change the state if it fails, then ;D

Dennis
Member #1,090
July 2003
avatar

I just tested yesterdays compiled version of my modified ex_keyboard_events again and found that all modifier keys and also extended keys like the arrow keys and numpad enter are correctly detected (you can tell by the white lines that blip up for each key which is correctly detected in a state).

torhu said:

Not even GetKeyState()? It doesn't always give the same result as GetKeyboardState().

I'll check if giving that key special treatment with GetAsyncKeyState or GetKeyState will allow for correct state detection.

edit:
Reading one of the other threads, I now know what you're talking about with the switch out/switch in problem and yes that could be easily fixed by clearing the state on switch out/switch in.

edit2:
Alright, I tested and debugged special GetKeystate and GetAsyncKeyState for the BREAK key. Neither is able to correctly detect the keystate.

I noticed though that Allegro treats that keypress as a so called 'dead key' and that on the windows system level, the window always gets a WM_KEYDOWN and an immediate following WM_KEYUP message for that key, regardless of its' actual physical state.

So yeah, can't ever detect that ones' state properly.

edit3:
Attached is a new patch which gets rid of the duplicate internal state and also clears the state when the window becomes inactive/loses input focus. That effectively prevents keys from getting 'stuck' in the state on switching away. see updated main post

Elias
Member #358
May 2000

Well, I committed it.

--
"Either help out or stop whining" - Evert

torhu
Member #2,727
September 2002
avatar

Not an ideal solution. I does the extra work every time al_get_keyboard_state is called, once every switch in would have gotten you the same result. And just clearing the state on switch out would have done so too, for all practical uses.

Elias
Member #358
May 2000

Hm, guess I was too fast applying that part then - but it's only one line anyway - once there is a better patch can easily apply that.

The main part of the patch of using the Windows state for al_get_keyboard_state sounds like a good idea though. (There is usually no reason to use that function of course, so it won't have much effect at all.)

--
"Either help out or stop whining" - Evert

torhu
Member #2,727
September 2002
avatar

Elias said:

The main part of the patch of using the Windows state for al_get_keyboard_state sounds like a good idea though.

Yes, if it wasn't for the fact that Allegro already maintains the keyboard state perfectly reliably in the_state. The only time it breaks is on switch in/out. I tested this for hours a few months back.

Basically, I would have replaced the whole patch with a single memset.

EDIT: Okay, and a call to update_toggle_modifiers().

EDIT2:
Also, updating the state on switch in is fine, instead of just clearing it. But doesn't need to happen more often than that. It's already taken care of.

EDIT3:

Dennis said:

I just tested yesterdays compiled version of my modified ex_keyboard_events again and found that all modifier keys and also extended keys like the arrow keys and numpad enter are correctly detected.

I don't think it's actually working. Does it differentiate between the two Enter keys, or are they just both mapped to ALLEGRO_KEY_ENTER? Things like that won't work, because you need more one than just the single byte to distinguish between them. And the numpad keys should map to the same ALLEGRO_KEY code independently of the state of Num Lock.

Thomas Fjellstrom
Member #476
June 2000
avatar

torhu said:

Allegro 4 treats it as a toggle key, don't know if that's better or worse...

AFAIK it is a toggle key. I think that's why windows "Breaks" (kekeke) it by adding in the immediate key up. You press it once, its active till you press it again. I thought scroll lock was similar.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Elias
Member #358
May 2000

torhu said:

Yes, if it wasn't for the fact that Allegro already maintains the keyboard state perfectly reliably in the_state. The only time it breaks is on switch in/out. I tested this for hours a few months back.

Hm, so should I revert it? I only tried it in Wine (which turned out to be pointless since Wine has an X11 bug where it messes up keyboard state itself :P).

So anyway, if there's a better patch, I'll apply that instead.

--
"Either help out or stop whining" - Evert

torhu
Member #2,727
September 2002
avatar

I don't have a better patch, but this patch in its current state is worse than no patch. I have tried to explain a few times now why that is. And I have tried to explain what a better patch would look like.

Dennis
Member #1,090
July 2003
avatar

I can make a new patch if you could just once more sum up a list of bullet points of what it should do.

torhu said:

I don't think it's actually working. Does it differentiate between the two Enter keys, or are they just both mapped to ALLEGRO_KEY_ENTER? Things like that won't work, because you need more one than just the single byte to distinguish between them. And the numpad keys should map to the same ALLEGRO_KEY code independently of the state of Num Lock.

Numpad Enter does work and sets the state flag for both the normal Enter and the Numpad Enter whereas the normal Enter only sets the state for the normal Enter and not the Numpad Enter, so if you test the state flag for Numpad Enter you can be sure that's what was pressed.

I noticed however that the number pad key states 1 to 9 do not get set if Numlock is off. The other extended key states (cursors, modifiers, etc do work).

EDIT:
As this thread is getting messy and there seem to have been a few communication problems and misunderstandings towards what the original patch was supposed to do, I made a new thread and a new patch (against latest SVN 5.1 where the other patch (rightly so) has already been reverted).
http://www.allegro.cc/forums/thread/610504

Arthur Kalliokoski
Second in Command
February 2005
avatar

I think that's why windows "Breaks" (kekeke) it by adding in the immediate key up.

IIRC, the Break key sends a weird identical sequence of bytes on press and release, so you need a flag to keep track of whether it's up or down. Don't you guys remember your DJGPP keyboard interrupt handlers? Windows apparently didn't bother to do this themselves.

They all watch too much MSNBC... they get ideas.

Elias
Member #358
May 2000

Here in X11 the pause key is just a normal key with a pressed event, then repeat events and a release event. Nothing special at all.

But since I can't test it in Windows this either means that I have a keyboard which did away with the special hardware for pause - or that only Windows adds all the special handling.

--
"Either help out or stop whining" - Evert

Dennis
Member #1,090
July 2003
avatar

Elias said:

Here in X11 the pause key is just a normal key with a pressed event, then repeat events and a release event. Nothing special at all.

I have a different keyboard connected now (USB, the other one was PS/2) and now the pause key on this one behaves just like that, key down, repeat, key up events and correct state too.

I think it's safe to conclude from that observation that it's not Windows' fault but a problem at the hardware level (the break key stuff). It may or may not be related to USB, PS/2, could even be different between different keyboard models.

Still, like I wrote before, the other issue with the modifier flags and the state getting out of sync is solved in a new patch: http://www.allegro.cc/forums/thread/610504

Go to: