August 15, 2018, 09:46:17 PM

Author Topic: Shift Key still reading as down after it has been released  (Read 341 times)

Offline IanMartin

  • Full Member
  • ***
  • Posts: 122
    • Retrolutionary.com
Shift Key still reading as down after it has been released
« on: February 07, 2018, 08:14:50 PM »
Has anyone found a solution to this bug?  Or is there a work around or another way to read the keyboard?  I have tried EVENT_KEYDOWN and EVENT_KEYUP to read the key position and I get the same result.

Bug:  Hold Left Shift, hold Right Shift, release Left Shift, Left Shift still reads as down.
Left Shift released code is never sent.

Code: [Select]
Graphics 800,600
While Not (KeyHit(KEY_ESCAPE) Or AppTerminate())

kd=KeyDown(key_lshift) Or KeyDown(key_rshift)
kdls=KeyDown(key_lshift)
kdrs=KeyDown(key_rshift)
DrawText "Either shift down?=" + kd, 0, 0
DrawText "Left shift down?=" + kdls, 0, 20
DrawText "Right shift down?=" + kdrs, 0, 40
DrawText "first put down left shift, and keep it down.", 0, 80
DrawText "then put down right shift, and keep it down,", 0, 100
DrawText "then RELEASE LEFT shift..", 0, 120
DrawText "then release right shift..", 0, 140
DrawText "THIS IS BUG: Either Shift DOWN="+kd, 0, 180

'BUG When you release right shift Shift status is 1 <=BUG
'This happens also when you first put down right shift. etc.

Flip
Cls
Wend

As you can see if you run this code, holding one shift key and then pressing the other results in the key showing as stuck down.  Similar bugs happen with other keys ,.? I think and pressing shift.  This would be no big deal in most cases, but if your game relies on showing which keys you are pressing or not pressing, which my current design does, it's a problem.

I have two keyboards and this happens on both of them.  Is this a Windows thing or a BlitzMax thing? 
Would this still happen in GameMaker or Unity, for instance?
Does anyone know another way to read the key states?

Platfinity (made with BlitzMax) on Steam:
http://store.steampowered.com/app/365440/Platfinity/

Offline Derron

  • Hero Member
  • *****
  • Posts: 1166
Re: Shift Key still reading as down after it has been released
« Reply #1 on: February 07, 2018, 08:23:41 PM »
Tested on linux.
Does not work for me - or in other words: releasing left shift while keeping the right one down - is recognized correctly.

Tested on XP in a VM
Bugged as you describe.


bye
Ron

Offline Derron

  • Hero Member
  • *****
  • Posts: 1166
Re: Shift Key still reading as down after it has been released
« Reply #2 on: February 07, 2018, 08:53:45 PM »
Just modified "brl.mod/system.mod/system.win32.c" to output some stuff.

This function there
Code: [Select]
void bbSystemEmitOSEvent( HWND hwnd,UINT msg,WPARAM wp,LPARAM lp,BBObject *source ){

It exists to create events if something "os specific" happens (mouse move, keyboard, app window things). And there is no "WM_KEYUP" event coming in if the second shift key is still hold. So it might be a "system issue" rather than a "blitzmax issue".


Edit: it happens to other keys too - the system only emits "key down" events - blitzmax should keep "keydown" state until it receives "WM_KEYUP" for the given key. For keys like "a" or "s" it works trouble free. But blitzmax-wise the "mechanics" are the same for shift and character keys. BlitzMax fills an array of the key codes with "1 or 0" (or hit counts). But it just does not receive the "left shift no longer hit" from the OS.

Edit2: The culprit is the "state manager" approach BlitzMax uses. Just do a "caps lock" while your app is focused. Now tab into another app, press "caps lock" again. If you now refocus to your app it still thinks it has activated caps lock.

Edit3: Seems Torque Engine had this problem too - in 2006 ;-)
https://www.garagegames.com/community/forums/viewthread/44841


When now following the suggestions where it sounds as if one should add "GetAsyncKeyState()"-calls to check if left/right shift are hit or not - instead of relying on the states defined by wm_keydown and wm_keyup. Disadvantage: wm_key**-events are queued, GetAsyncKeyState() requests the current key state - which might differ (timestamp wise) from the queued wm_key** thingies.

bye
Ron

Offline IanMartin

  • Full Member
  • ***
  • Posts: 122
    • Retrolutionary.com
Re: Shift Key still reading as down after it has been released
« Reply #3 on: February 07, 2018, 10:01:23 PM »
I found some old threads about it on the old Blitzbasic.com site.  They never seem to have found a resolution to it.  Those posts were very old as well.

The GetAsyncKeyState(), is that in torque?  How would I do that in BlitzMax?

I don't need a super elegant solution to this for the game I'm doing now, I just need the graphic of the shift key to match what the user is doing on their keyboard.  So if there's a way to reset the state or read it another way, that would work for me but I guess the bug is still not resolved. 

Maybe reset the other shift key when the second one is pressed?  That would kind of make sense to the user as it's showing the last one they hit.  Gameplay wise it makes no difference which shift is down, it only matters to the graphical effect.

Thanks for looking into this!
Platfinity (made with BlitzMax) on Steam:
http://store.steampowered.com/app/365440/Platfinity/

Offline Derron

  • Hero Member
  • *****
  • Posts: 1166
Re: Shift Key still reading as down after it has been released
« Reply #4 on: February 07, 2018, 10:14:31 PM »
GetAsyncKeyState() is something "available" on Windows OS. Think one could expose that to BlitzMax via some "external" command or so. Am not experienced in this, so I would let that up for people with the knowledge to do so.



Resetting the key states requires modification of brl.mod/polledinput.mod  - as "Keystates:int[]" is private and not accessible from the outside.


if you are not interested in proper "key down - key up" information but just "was down somewhen but now the other shift is hit and it does not matter if the left is still hit" then you could have your own variables?
So if you need to hit "left shift", then "right shift" and then "something else" you would reset your variables once you reach "something else" step. The idea is to ignore the "wrong" information about a shift key still being down.


But what you describe is saying: highlight a key-graphics of the key currently being hit/down. And this is not working as you have an invalid state ("key down"). So the only solution for a real time "key down"-observation seems to be something in the likes of GetAsyncKeyState().

Edit: ok, got some code working - will post it in the next minutes, just adding some "convenience".



bye
Ron

Offline Derron

  • Hero Member
  • *****
  • Posts: 1166
Re: Shift Key still reading as down after it has been released
« Reply #5 on: February 07, 2018, 10:29:05 PM »
Append this to your code (and make sure to write SuperStrict code - your sample accesses undefined variables which are not have something assigned in all cases).

Code: [Select]
Import Pub.Win32

Extern "Win32"
   Function GetAsyncKeyState:Short(key:Int)
End Extern

Function MyKeyDown:Int(key:Int)
   ?win32
   Select key
      Case KEY_LSHIFT, KEY_RSHIFT, KEY_LSYS, KEY_RSYS, KEY_LCONTROL, KEY_RCONTROL, KEY_LALT, KEY_RALT
         'least significant bit tells if "down" or not - according to MSDN
         Return GetAsyncKeyState(key) Shl 16 Shr 31
      Default
         Return KeyDown(key)
   End Select
   ?

   ?Not win32
   Return KeyDown(key)
   ?
End Function
(Pub.Win32 is what makes the function available to us)


It should only do this stuff on win32, for linux/mac it relies on KeyDown(). I use that Async-call for all "special keys" which exist in a left/right form. Remove the "case"-entries if this is not needed.


Edit: once I knew how it works, I was able to find some German posts doing similar stuff - they do some Shl/Shr stuff for the bit recognition - I added them in. Ok, they define the function as ":int" while msdn defines it as :short (which is why I do the same).
Here is a (German) thread creating a "AsyncKeyDown()" and "AsyncKeyHit()" function:

https://www.blitzforum.de/forum/viewtopic.php?t=34700

I am not sure if the "Bit shifting" is working with NG then (64 bit targets) - so there might be some adjustments needed, or an "<> 0" is working too?


bye
Ron

Offline IanMartin

  • Full Member
  • ***
  • Posts: 122
    • Retrolutionary.com
Re: Shift Key still reading as down after it has been released
« Reply #6 on: February 07, 2018, 11:20:14 PM »
Holy crap that works!

Code: [Select]
Import Pub.Win32

SuperStrict

Global KD:Int ; Global KDLS:Int ; Global KDRS:Int


Extern "Win32"
   Function GetAsyncKeyState:Short(key:Int)
End Extern


Function MyKeyDown:Int(key:Int)
   ?win32
   Select key
      Case KEY_LSHIFT, KEY_RSHIFT, KEY_LSYS, KEY_RSYS, KEY_LCONTROL, KEY_RCONTROL, KEY_LALT, KEY_RALT
         'least significant bit tells if "down" or not - according to MSDN
         Return GetAsyncKeyState(key) Shl 16 Shr 31
      Default
         Return KeyDown(key)
   End Select
   ?

   ?Not win32
   Return KeyDown(key)
   ?
End Function


Graphics 800,600

While Not (KeyHit(KEY_ENTER) Or AppTerminate())

KD=KeyDown(key_lshift) Or KeyDown(key_rshift)
KDLS=KeyDown(key_lshift)
KDRS=KeyDown(key_rshift)
DrawText "Original KeyDown", 0, 0
DrawText "Either shift down?=" + KD, 0, 40
DrawText "Left shift down?=" + KDLS, 0, 60
DrawText "Right shift down?=" + KDRS, 0, 80
DrawText "first put down left shift, and keep it down.", 0, 100
DrawText "then put down right shift, and keep it down,", 0, 120
DrawText "then RELEASE LEFT shift..", 0, 140
DrawText "then release right shift..", 0, 160
DrawText "THIS IS BUG: Either Shift DOWN="+KD, 0, 180

DrawText "ENTER to try MyKeyDown", 0, 200
'BUG When you release right shift Shift status is 1 <=BUG
'This happens also when you first put down right shift. etc.

Flip
Cls
Wend

Cls

While Not (KeyHit(KEY_ENTER) Or AppTerminate())

KD=MyKeyDown(key_lshift) Or MyKeyDown(key_rshift)
KDLS=MyKeyDown(key_lshift)
KDRS=MyKeyDown(key_rshift)
DrawText "MyKeyDown", 0, 0
DrawText "Either shift down?=" + KD, 0, 40
DrawText "Left shift down?=" + KDLS, 0, 60
DrawText "Right shift down?=" + KDRS, 0, 80
DrawText "first put down left shift, and keep it down.", 0, 100
DrawText "then put down right shift, and keep it down,", 0, 120
DrawText "then RELEASE LEFT shift..", 0, 140
DrawText "then release right shift..", 0, 160
DrawText "NO MORE BUG: Either Shift DOWN="+KD, 0, 180

DrawText "ENTER to quit", 0, 200

Flip
Cls
Wend

This is awesome!  Thanks so much for your help!  I was entertaining the thought of removing the Shift Key graphics.  Now I won't have to do that.  Thanks again for helping me :)
Platfinity (made with BlitzMax) on Steam:
http://store.steampowered.com/app/365440/Platfinity/

Offline Brucey

  • Jr. Member
  • **
  • Posts: 52
Re: Shift Key still reading as down after it has been released
« Reply #7 on: February 09, 2018, 05:19:33 PM »
Hi ho.

I'll have a look at implementing this in my legacy BRL module, as well as for the default BRL event handler in NG.

On a brighter note, the SDL backend appears to work as expected :-)

Offline IanMartin

  • Full Member
  • ***
  • Posts: 122
    • Retrolutionary.com
Re: Shift Key still reading as down after it has been released
« Reply #8 on: February 10, 2018, 04:02:02 AM »
Sounds awesome, Brucey! :)
Platfinity (made with BlitzMax) on Steam:
http://store.steampowered.com/app/365440/Platfinity/

Offline Brucey

  • Jr. Member
  • **
  • Posts: 52
Re: Shift Key still reading as down after it has been released
« Reply #9 on: February 13, 2018, 07:09:18 AM »
Hallo,

I've pushed a fix to my legacy BRL module : https://github.com/maxmods/brl.mod
This now handles the special case on Win32 when the two shift keys are pressed at the same time, and then fail to raise an event when one of them is released.
(note : if you are going to replace the official BRL modules with that one, you probably want to get my PUB modules too... from the same place. Otherwise, the commit (https://github.com/maxmods/brl.mod/commit/fdb1d27ca79f450b02cba928b968a53168315a6c) shows what changes were made, were you to want to apply them to your own BRL modules.)

It's also been included in NG's BRL.SystemDefault module. The SDL event handler already manages this Win32 "feature".

:o)

Offline Derron

  • Hero Member
  • *****
  • Posts: 1166
Re: Shift Key still reading as down after it has been released
« Reply #10 on: February 13, 2018, 08:23:23 AM »
As suggested to Brucey by mail already:


I think it would be a good idea to refresh key states when doing "app switches" (alt-tabbing). So gaining focus after loosing it: compare "live key states" with the last known ones (keyHitState[]). If it changed meanwhile, emit an blitzMax-"OS"event so as if it just received a "keydown/keyup" event from the system.


That way you avoid the odd behaviour when eg. holding down "a", alt-tab out, release "a", alt-tab in. If you do that now, blitzMax thinks you are still holding down "a" until you tap it once.


What do you think about this issue?
Fixing should not be that much of a hassle (very similar to the current fix for shift).


bye
Ron

Offline IanMartin

  • Full Member
  • ***
  • Posts: 122
    • Retrolutionary.com
Re: Shift Key still reading as down after it has been released
« Reply #11 on: February 13, 2018, 01:47:47 PM »
I think that would be a good idea!  People really like to Alt-Tab out a lot these days.  I can see them holding a key, the gas pedal key maybe(?), tabbing out and back in, and then saying the gas is stuck on.  Little bugs like that.  I think we're past the point that people will accept that they caused the bug by Alt-Tabbing.  Games always seem like an arms race trying to check all the little boxes, heheh
Platfinity (made with BlitzMax) on Steam:
http://store.steampowered.com/app/365440/Platfinity/