|
Windows: al_get_keyboard_state patch for 5.0.6 SVN |
Dennis
Member #1,090
July 2003
|
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. 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. --- 0xDB | @dennisbusch_de --- |
torhu
Member #2,727
September 2002
|
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:
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: |
Dennis
Member #1,090
July 2003
|
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.
1. will check, thought the ALLEGRO_KEYBOARD_STATE did not have a field for modifier keys...at least I could not find one EDIT: --- 0xDB | @dennisbusch_de --- |
torhu
Member #2,727
September 2002
|
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 |
Dennis
Member #1,090
July 2003
|
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: edit2: 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: --- 0xDB | @dennisbusch_de --- |
Elias
Member #358
May 2000
|
Well, I committed it. -- |
torhu
Member #2,727
September 2002
|
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.) -- |
torhu
Member #2,727
September 2002
|
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: 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
|
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. -- |
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 ). So anyway, if there's a better patch, I'll apply that instead. -- |
torhu
Member #2,727
September 2002
|
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
|
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: --- 0xDB | @dennisbusch_de --- |
Arthur Kalliokoski
Second in Command
February 2005
|
Thomas Fjellstrom said: 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. -- |
Dennis
Member #1,090
July 2003
|
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 --- 0xDB | @dennisbusch_de --- |
|