I just realized something about rawKeyDown/rawKeyUp (as well as keyDown/keyUp) that has become problematic for me. I mistakenly assumed that (in a field where someone is typing) if I receive a rawKeyDown, I should receive that keystroke's rawKeyUp before the next keystrokes rawKeyDown....of course I was wrong....
If someone quickly types 'abc', many times they are striking the 'b' key before the 'a' key is actually released. This renders logic that assumes a rawKeyUp would be sent before the next key's rawKeyDown totally useless. I don't know how I didn't realize this earlier in my development, I guess my software is getting in the hands of faster typists.
Has anyone ever faced the dilemma of wanting to do things in rawKeyDown/rawKeyUp handlers and faced the situation where two rawKeyDown messages are sent before receiving the initial key's rawKeyUp?
Thank you!
rawKeyDown/rawKeyUp seemingly out of sequence
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
Re: rawKeyDown/rawKeyUp seemingly out of sequence
Hi,
I have not faced precisely this challenge with synchronising rawKeyDown/Up and keyDown/Up, but have had to ensure mouseDown/Up synchronisation. Unexpected problems can emerge when a proficient user operates at speed. Some of these ideas may be of use in your case. To investigate the current problem, I created a new test stack, and put in three text fields of reasonable size, named:
card field “CharacterOutput”
card field “RawOutput”
card field “TestTyping”
... along with a button, whose script is:
... so I can easily clear the fields with a sweep of the mouse..
To see what is happening when keys are pressed, I wrote the following as a script for card field “TestTyping”:
... and with this script, by alternately typing the characters “a” then “b”, at a modest pace, the output is “echoed” thus:
in card field “CharacterOutput”
a(d) a(u) b(d) b(u)
in card field “RawOutput”
97(d) 97(u) 98(d) 98(u)
... which is as it should be.
Typing at speed introduces problems:
in card field “CharacterOutput”
a(d) b(d) b(u)
... the keyUp for “a” is blocked by the “b”
and two possible problems in card field “RawOutput”
97(d) 98(d) 97(u) 98(u)
... where the key presses of “a” and “b” are “interlaced”, and
97(d) 98(d) 98(u) 97(u)
... where, while the “a” is pressed, the “b” is pressed and released, and then the “a” released. Note that the typing that appears in card field “TestTyping” is normal in both cases.
Replacing the script of card field “TestTyping” with the following:
... we continue to have the downs/ups “echoed” in line 1 of the output fields, but with corrected output in line 2. Both keyDown and rawKeyDown adjustments look for a double “down”- if a keyDown is received, with the keyState still “d” (i.e. it was not switched back to “u” by a keyUp), keyDown takes corrective action. I have used separate variables for keyDown and rawKeyDown, so they don’t interfere with each other. rawKeyDown is more complex, to cope with the variety of problem cases. It took a diagram to work out the logic, so it is difficult to explain in words. It may be clearer if we consider how the solution might be applied to something more interesting than simply echoeing the keystrokes. What you would need to do is “break out” the parts of rawKeyDown/Up you want executed into separate handlers, say PressDown and ReleaseUp. You would then re-write the rawKeyDown/Up script thus:
... as I am don’t know exactly where these handlers are placed in your application, I have included the globals explicitly. It would be important to include keyToUse as a global available to PressDown and ReleaseUp, for correct operation. The above solution may not meet your needs, and I have tested it as much as possible, but I still may have tripped up somewhere. One observation I can make is that whatever happens in PressDown and ReleaseUp must be efficiently programmed, as a proficient typist will be “firing” them rapidly (which is the source of the current problem anyway), so slower processes can “queue up”, causing problems. Please don’t hesitate to let me know if I’ve made a mistake, been unclear, or am simply wide of the mark. It’s an interesting problem which may take some “tinkering” to solve.
I have not faced precisely this challenge with synchronising rawKeyDown/Up and keyDown/Up, but have had to ensure mouseDown/Up synchronisation. Unexpected problems can emerge when a proficient user operates at speed. Some of these ideas may be of use in your case. To investigate the current problem, I created a new test stack, and put in three text fields of reasonable size, named:
card field “CharacterOutput”
card field “RawOutput”
card field “TestTyping”
... along with a button, whose script is:
Code: Select all
on mouseEnter
put empty into card field "CharacterOutput"
put empty into card field "RawOutput"
put empty into card field "TestTyping"
end mouseEnter
To see what is happening when keys are pressed, I wrote the following as a script for card field “TestTyping”:
Code: Select all
on keyDown keyValue
put space&keyValue&"(d)" after line 1 of card field "CharacterOutput"
pass keyDown
end keyDown
on keyUp keyValue
put space&keyValue&"(u)" after line 1 of card field "CharacterOutput"
pass keyUp
end keyUp
on rawKeyDown keyValue
put space&keyValue&"(d)" after line 1 of card field "RawOutput"
pass rawKeyDown
end rawKeyDown
on rawKeyUp keyValue
put space&keyValue&"(u)" after line 1 of card field "RawOutput"
pass rawKeyUp
end rawKeyUp
in card field “CharacterOutput”
a(d) a(u) b(d) b(u)
in card field “RawOutput”
97(d) 97(u) 98(d) 98(u)
... which is as it should be.
Typing at speed introduces problems:
in card field “CharacterOutput”
a(d) b(d) b(u)
... the keyUp for “a” is blocked by the “b”
and two possible problems in card field “RawOutput”
97(d) 98(d) 97(u) 98(u)
... where the key presses of “a” and “b” are “interlaced”, and
97(d) 98(d) 98(u) 97(u)
... where, while the “a” is pressed, the “b” is pressed and released, and then the “a” released. Note that the typing that appears in card field “TestTyping” is normal in both cases.
Replacing the script of card field “TestTyping” with the following:
Code: Select all
on keyDown keyValue
global keyState, CharacterStore
put space&keyValue&"(d)" after line 1 of card field "CharacterOutput"
if keyState = "d" then
put space&CharacterStore&"(u)" after line 2 of card field "CharacterOutput"
end if
put space&keyValue&"(d)" after line 2 of card field "CharacterOutput"
put keyValue into CharacterStore
put "d" into keyState
pass keyDown
end keyDown
on keyUp keyValue
global keyState
put space&keyValue&"(u)" after line 1 of card field "CharacterOutput"
put space&keyValue&"(u)" after line 2 of card field "CharacterOutput"
put "u" into keyState
pass keyUp
end keyUp
on rawKeyDown keyValue
global rawKeyState, keyStore, bypassRawKeyUp
put space&keyValue&"(d)" after line 1 of card field "RawOutput"
if rawKeyState = "d" then
put space&keyStore&"(u)" after line 2 of card field "RawOutput"
put "yes" into bypassRawKeyUp
end if
put space&keyValue&"(d)" after line 2 of card field "RawOutput"
put keyValue into keyStore
put "d" into rawKeyState
pass rawKeyDown
end rawKeyDown
on rawKeyUp keyValue
global rawKeyState, bypassRawKeyUp, keyStore
put space&keyValue&"(u)" after line 1 of card field "RawOutput"
if bypassRawKeyUp = "yes" then
if keyValue <> keyStore then
put "no" into bypassRawKeyUp
pass rawKeyUp
end if
end if
put space&keyValue&"(u)" after line 2 of card field "RawOutput"
put "u" into rawKeyState
pass rawKeyUp
end rawKeyUp
Code: Select all
on rawKeyDown keyValue
global rawKeyState, keyStore, bypassRawKeyUp, keyToUse
if rawKeyState = "d" then
put keyStore into keyToUse
ReleaseUp
put "yes" into bypassRawKeyUp
end if
put keyValue into keyToUse
PressDown
put keyValue into keyStore
put "d" into rawKeyState
pass rawKeyDown
end rawKeyDown
on rawKeyUp keyValue
global rawKeyState, bypassRawKeyUp, keyStore, keyToUse
if bypassRawKeyUp = "yes" then
if keyValue <> keyStore then
put "no" into bypassRawKeyUp
pass rawKeyUp
end if
end if
put keyValue into keyToUse
ReleaseUp
put "u" into rawKeyState
pass rawKeyUp
end rawKeyUp