[jawsscripts] Re: KeyWaiting function and best results?

  • From: "Steve Spamer" <stevespamer68@xxxxxxxxx>
  • To: <jawsscripts@xxxxxxxxxxxxx>
  • Date: Thu, 25 Oct 2018 15:38:12 +0100

Jim and Doug. I'm just digesting this information and a question arises.

If i was to copy PassKeyThrough for each arrow key, and give it another 
name, then replace the actual key currently assigned, which passes it 
through, with a left or right arrow key, wouldn't this solve both scenarios? 
Then, when pressing those arrow keys, it is always being passed through, 
hence always using the native action?

So, the user presses once.
The key is passed through, but instead of using the jaws key+3, it uses say 
the right arrow.
So we get the press followed by the SayPosition spoken.
Then, if IsKeyWaiting, again it's passed through, but with that initial 
press.

As with all of this, it sounds simple, but is probably off the mark.  One 
thing I'm not sure about here, is the line in the PassKeyThrough script:
;cmsg43_L = "Enter key to pass thru"

Now, is the words enclosed in quotes the place where the replacement key 
should be?  Should this be the script name, a literal string like 
"LeftArrow" or something else?...or is the cmsg43_L this key that should be 
replaced?

There is also the last line which calls PassKeyThrough(), again not sure why 
that is there.



-----Original Message----- 

Just trying to decide which method to try first. THX Steve.
From: Doug Lee
Sent: Thursday, October 25, 2018 10:39 AM
To: jawsscripts@xxxxxxxxxxxxx
Subject: [jawsscripts] Re: KeyWaiting function and best results?

There was a similar discussion here recently where I said something similar 
to what follows:

Remember that the PassKeyThrough function does not send a just-typed key 
through to the application. It causes the next key typed to be sent through 
to the application, just like its script cousin that is invoked with Ins+3. 
In
fact, that is why Ins+3 works: Here is the PassKeyThrough script from 
default.jss:

script PassKeyThrough()
;cmsg43_L = "Enter key to pass thru"
SayFormattedMessage (ot_JAWS_message, cmsg43_L, cmsg43_S)
PassKeyThrough()
EndScript

TypeCurrentScriptKey sends the key through that invoked the current script. 
If you need to send a different key, use TypeKey(). TypeCurrentScriptKey can 
be called from within a function that is called by a script, and still
work as expected.

Scheduling logic from a script to keep it from running too fast on rapid key 
presses is a tactic I've used myself. It does have the mentioned 
disadvantage of slowing the first reaction to a keystroke though.

How far off, then, is this code snippet for the original problem? Notice I 
allow "forward" to be passed to a function shared between two scripts; but 
in this case, it is probably not needed. Also note that I added a pause()
call before announcing position, so that the last audio skip can settle 
before we try to announce anything.

script sayNextCharacter()
if skipAudio(True)
return
endIf
performScript sayNextCharacter()
endScript

script sayPriorCharacter()
if skipAudio(False)
return
endIf
performScript sayPriorCharacter()
endScript

void function skipAudio(int forward)
If (GetFocus() != GetArranger())
; This is not our case, so let the calling script handle it.
return False
endIf
typeCurrentScriptKey()  ; forward or backward as appropriate
If IsKeyWaiting ()
; Stop, no position announcement.
; Return True though so the calling script knows the keystroke has been 
processed.
return True
endIf
pause()  ; Let the skip settle before we speak
SayPosition()
return True
endFunction

On Wed, Oct 24, 2018 at 09:12:53PM -0500, Snowman wrote:
It seems like the basic problem is that, when the first key stroke is
processed, you can't tell if this key stroke is a singular event,  or if it
is part of a rapid fire sequence.  but, you would like to know that.
I can't think of a way to distinguish those from within a script.  Even
GetKeyState wont' work if the user doesn't lift their finger quickly enough
on a single strike.

One thing I have done, and my have mentioned before, is to put the logic of
this script into a function,  and just have this script schedule that
function.
Rename these variables to suit your taste.


global
  int xTaskID

const
    keyDelayTime 1 ; fine tune this number

script x()
If (GetFocus() == GetArranger()) Then
    if (xTaskId) then
        ; the function  still has not run
        PassKeyThrough()
        unscheduleFunction (xTaskID) ; cancel that
    endif
    let xTaskID = ScheduleFunction ("y", keyDelayTime)
EndScript

function Y()
; send the key to the application?
; speak the result?
Let xTaskID = 0 ; indicate that we ran
EndFunction

Here is the thought process on how this would work.
Single Press.  The function is scheduled, and, after keyDelayTime,  actually
gets to run,
the function sends the key to the application, and then speaks the result.
If you want to share that function, such as between left and right arrow,
you need a way to know which key to send.  GetCurrentScriptKey might be
based on the most recent key pressed.  I'm not sure.  Or, you can have a
global where you store it from your KeyPressedEvent.  But, I think there is
a way to get the most recently pressed key stroke.

Second scenario, User holds down the key.
The first press schedules the function, but no key is sent, because the
script thinks the function will run. So, we are one key short at this point.
Second key stroke arrives, and finds that xTaskID is not 0, meaning that the
previously scheduled run did not happen.
So, we cancel that, send the key to the application, and schedule another
function run.  This continues for each subsequent stroke, until the last
one.
When the last stroke hits the script, same thing happens. We notice the
function did not run, and send the key stroke, unschedule the function and
re-schedule it.  We are still one key behind.
If no more key strokes arrive, the schedule timer will expire, and the
function will finally run.  It issues the key stroke to the app one more
time, which should catch us up, and then it does the speaking.

One minor draw back to that approach, is that there will be a slight delay,
depending on keyDelayTime, from keystroke, until the event actually happens.
Anyway,  it's an idea.



.




+--------------------------------------------------------------------------+
Listen to The Snowman on MushroomFM.com, Saturday evenings, 8PM Eastern
time.
60's and 70's tunes, and gently conservative talk.

----- Original Message ----- 
From: "Steve Spamer" <stevespamer68@xxxxxxxxx>
To: <jawsscripts@xxxxxxxxxxxxx>
Sent: Wednesday, October 24, 2018 5:33 AM
Subject: [jawsscripts] KeyWaiting function and best results?


Hi folks.  A couple of weeks ago I was put on to the IsKeyWaiting function
to achieve a specific objective.  My question is, has anyone got advice on
the best/most optimal way to use this function for the scenario I face?

At the moment, I am really happy with how it's performing in both the below
examples, but with 1 caveat, which I'll explain.

First the current example, followed by a slight change I've tried, along
with how the app works and what behaviour I want...and this shows the
caveat.

If (GetFocus() == GetArranger()) Then
If IsKeyWaiting () Then
    PassKeyThrough ()
    Return
        Else
;            TypeCurrentScriptKey ()
            SayPosition()
EndIf
EndIf

On Wed, Oct 24, 2018 at 09:12:53PM -0500, Snowman wrote:
It seems like the basic problem is that, when the first key stroke is
processed, you can't tell if this key stroke is a singular event,  or if it
is part of a rapid fire sequence.  but, you would like to know that.
I can't think of a way to distinguish those from within a script.  Even
GetKeyState wont' work if the user doesn't lift their finger quickly enough
on a single strike.

One thing I have done, and my have mentioned before, is to put the logic of
this script into a function,  and just have this script schedule that
function.
Rename these variables to suit your taste.


global
  int xTaskID

const
    keyDelayTime 1 ; fine tune this number

script x()
If (GetFocus() == GetArranger()) Then
    if (xTaskId) then
        ; the function  still has not run
        PassKeyThrough()
        unscheduleFunction (xTaskID) ; cancel that
    endif
    let xTaskID = ScheduleFunction ("y", keyDelayTime)
EndScript

function Y()
; send the key to the application?
; speak the result?
Let xTaskID = 0 ; indicate that we ran
EndFunction

Here is the thought process on how this would work.
Single Press.  The function is scheduled, and, after keyDelayTime,  actually
gets to run,
the function sends the key to the application, and then speaks the result.
If you want to share that function, such as between left and right arrow,
you need a way to know which key to send.  GetCurrentScriptKey might be
based on the most recent key pressed.  I'm not sure.  Or, you can have a
global where you store it from your KeyPressedEvent.  But, I think there is
a way to get the most recently pressed key stroke.

Second scenario, User holds down the key.
The first press schedules the function, but no key is sent, because the
script thinks the function will run. So, we are one key short at this point.
Second key stroke arrives, and finds that xTaskID is not 0, meaning that the
previously scheduled run did not happen.
So, we cancel that, send the key to the application, and schedule another
function run.  This continues for each subsequent stroke, until the last
one.
When the last stroke hits the script, same thing happens. We notice the
function did not run, and send the key stroke, unschedule the function and
re-schedule it.  We are still one key behind.
If no more key strokes arrive, the schedule timer will expire, and the
function will finally run.  It issues the key stroke to the app one more
time, which should catch us up, and then it does the speaking.

One minor draw back to that approach, is that there will be a slight delay,
depending on keyDelayTime, from keystroke, until the event actually happens.
Anyway,  it's an idea.



.




+--------------------------------------------------------------------------+
Listen to The Snowman on MushroomFM.com, Saturday evenings, 8PM Eastern
time.
60's and 70's tunes, and gently conservative talk.

----- Original Message ----- 
From: "Steve Spamer" <stevespamer68@xxxxxxxxx>
To: <jawsscripts@xxxxxxxxxxxxx>
Sent: Wednesday, October 24, 2018 5:33 AM
Subject: [jawsscripts] KeyWaiting function and best results?


Hi folks.  A couple of weeks ago I was put on to the IsKeyWaiting function
to achieve a specific objective.  My question is, has anyone got advice on
the best/most optimal way to use this function for the scenario I face?

At the moment, I am really happy with how it's performing in both the below
examples, but with 1 caveat, which I'll explain.

First the current example, followed by a slight change I've tried, along
with how the app works and what behaviour I want...and this shows the
caveat.

If (GetFocus() == GetArranger()) Then
If IsKeyWaiting () Then
    PassKeyThrough ()
    Return
        Else
;            TypeCurrentScriptKey ()
            SayPosition()
EndIf
EndIf

Ok, so in the above example, the user presses the right arrow key at a
certain speed and they are move along a transport by 1 bar.
If that speed, I think, exceeds what the IsKeyWaiting function considers to
be a key waiting, then it passes the key through, allowing the audio to be
skipped without any influence from the script, which is the behaviour
wanted, so for example, if they hold the key down.
The caveat is in this scenario, is that if the user presses very quickly,
then the pass key through reduces the amount of thimes they press by 1.
So, if they press 10 times very quickly, the transport will report it's
moved 9 times, as the pass key through is counted and that press.

What I want to avoid is the key to be in the KeyWaiting buffer, as this
triggers things as if the script is typing the key and it slows things down,
but equally, I want every press to be counted correctly.

So, I have also tried putting the TypeCurrentScript above the IsKeyWaiting,
so:

If (GetFocus() == GetArranger()) Then
            TypeCurrentScriptKey ()
If IsKeyWaiting () Then
    PassKeyThrough ()
    Return
        Else
;            TypeCurrentScriptKey ()
            SayPosition()
EndIf
EndIf

This also works as I want, and it also reports correctly, but without this
being tested on a number of different/less powerful machines, I have no idea
if this the prefered method.

It's easy to say, but I just want to try and avoid this function slowing the
movement down, without first releasing the scripts, as the testers I have
all have machines that will handle both ways, so I currently don't have a
way to see if this will have an impact on lesser machines.  I have tried
looking for the IsKeyWaiting function, but I'm unable to find it, as I was
thinking, maybe I would be able to adjust the time that the function waits,
before it considers that the key is actually waiting.

So, in summary, when the user presses once, the type key is triggered and
the position is spoken. If they press quickly or hold the key down, then the
app is just doing it's default action with no influence from the scripts,
but most importantly, positions are correctly reported according to how many
times they pressed.  Does anyone know which of the examples written above
would be the best way of attack, or if there is a different approach that
will give me the results I want.  THX Steve.

Follow me on Twitter: @stevesax123
Visit the samplitude Access website. Jaws scripts for pro recording with
Samplitude in Windows: www.samplitudeaccess.org.uk

__________???

View the list's information and change your settings at
http://www.freelists.org/list/jawsscripts

__________???

View the list's information and change your settings at
http://www.freelists.org/list/jawsscripts

-- 
Doug Lee, Senior Accessibility Programmer
Level Access - over 1,000 organizations trust us to help them achieve and 
maintain digital accessibility compliance!
mailto:Doug.Lee@xxxxxxxxxxxxxxx  http://www.LevelAccess.com
"While they were saying among themselves it cannot be done, it was 
done." --Helen Keller
__________�

View the list's information and change your settings at
http://www.freelists.org/list/jawsscripts ;

__________�

View the list's information and change your settings at 
http://www.freelists.org/list/jawsscripts

Other related posts: