Welcome to BX, the JAWS toolbox!
BX falls under the BSD license as it appears below:
Copyright (c) 2006-2013, Doug Lee and SSB BART Group
All rights reserved
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
BX is a very comprehensive navigation and testing tool. It will allow you to test many JAWS scripting functions without writing scripts. Using BX, you will be able to use single keystrokes to get the results of most any function in each of the following categories:
|Window Functions||Go to first, last, parent, child, next, previous, current, focus, real, foreground, top-level, or other windows directly; and get a window's class, name, control ID, display style, dimensions and location, contents, etc.|
|SDM Window Functions||Move to first, last, next, previous, current, or focused SDM control and test all functions you might use to present the control to the user. This navigation is not possible in JAWS' home-row or Script Utility mode.|
|Cursor-Sensitive Functions||Use any standard JAWS navigation or cursor-changing/routing
command, plus a few for moving by other units such as text chunks; and
test cursor-sensitive functions such as
|JAWS Object Functions||Navigate with cursors as above and test functions like
|Java and Nav Module Functions||Test JAWS functions for dealing directly with Java controls, including the Nav Module system functions introduced in JAWS 5.0.|
|Global (non-location-specific) Functions||Test functions such as
|Program-specific Functions||Find out the version number or version info strings for the active application, the name and version information for the current application or default script files, etc.|
|COM Object Functions||Find out if any of the JAWS functions returning COM object interfaces work from the current cursor location.|
Additionally, you will be able to do all of the following:
GetItemRectfunction in detail to find out what is returned for specific unit requests.
Finally, power users may customize the BX interface or add commands by editing a .ini-style file and using a BX-specific syntax that permits scripts and functions to be called directly from a text file without the need to compile new code.
BX works with JAWS versions 5.0 and up. BX may contain features that only work in newer versions of JAWS. These features will fail under older versions of JAWS, but this will not prevent BX from performing properly otherwise. In other words, BX will do its best to adapt to what it can find and will do as much as it can.
BX is activated via the command that normally activates JAWS home-row mode, or Script Utility mode as it is called starting in JAWS 11. For JAWS 10 and older, this command was JAWSKey+Space on most systems. By default, pressing this command once will enter BX mode, and pressing it twice in quick succession will enter JAWS' normal home-row mode instead. (BX can easily be configured to enter home-row mode on a single press and BX mode on a double press if desired.) When in either BX or home-row mode, typing this command while in BX will return you to normal operation.
In JAWS' original home-row mode, you had a location, defined by a window handle, and a set of possible commands. The possible keystrokes never changed, but their output did: You could cycle through output modes with f3 and through attribute search types with f4 and thus change the effects of other commands.
BX extends these concepts significantly. In BX, a
"location" is simply a sufficient set of information to define where
you are. Your current location could be a window (as in home-row
mode), an SDM control, an MSAA object, a cursor position, etc.
Naturally, each different type of location has associated with it a
unique set of possible commands, corresponding to the things you can
do there. When in a window, you might want its class; when on an SDM
control, you might want to hear the result of calling
SDMSayControl; and when examining an MSAA object, you
might want to hear its name and role. You might even want to combine
various means of navigation to achieve one goal, such as by finding a
list box by navigating the window tree, then getting that window's MSAA client object
(which will be a Role_System_List object), and finally using arrows
to read all the list items whether or not they are shown on screen.
Because there are a number of different environments in BX, each with
its own unique requirements and capabilities, there will be different
commands available depending on where you are. Whenever possible,
command structure was made uniform across environments:
To move to the first, last,
previous, or next location from the current one in any mode, use
home, end, up arrow, and down
arrow, respectively (except when using screen coordinates as
locations, at which time all normal JAWS movement commands will work as
expected). Commands for which uniformity is impossible or
unreasonable tend to have mnemonic key assignments: c for
window class, i for control ID, etc. Finally, some
conventions apply for grouping commands. For instance, commands that jump to
a new location by means other than relative movement are activated with keys
involving the control key. Thus, when navigating among
windows, control+f will jump to the window in focus, and
control+r will jump to the "real" window (the first window above
the current one with a title).
Say commands and commands
that affect the environment, such as by changing focus, tend to
involve the alt key; thus, during Window Navigation,
SayWindowTypeAndText and alt+f
In summary then, BX is simply a system which gives you the ability to navigate among locations and between types of locations and to test numerous JAWS scripting functions pertinent to each type of location. As such, it is of primary and considerable use to scripters; however, it is also very helpful as an instructional tool for those wishing to learn how to write scripts, and it can sometimes be used as a very effective means of handling application accessibility problems on the fly--for example, setting focus to an otherwise unreachable control, monitoring the progress of a long operation by parking on an MSAA progress control and pressing v periodically to check the position of the gauge, etc.
There are several help facilities in BX which will be explained shortly. It is not necessary to memorize a lot of commands right away; you can find them all interactively. However, before presenting the help system, this section will do a little to explain common BX usage.
The most frequent type of BX usage involves turning BX on, choosing the map you want (for example, 'w for Window Navigation or 'm for MSAA Navigation), setting a starting point (for example, control+f to move to the current location of focus), and starting to navigate and test functions and properties. An example: To find the name of the current window and the class of the top-level window above it in the window tree, you could do the following:
Here is a list of basic commands that should help you figure out the rest of them. These commands work in all key maps except where noted. A few commands, shown at the end of this list, are not really related to the help system but are helpful in just about any map sometimes.
|JAWSKey+1 (normal JAWS Keyboard Help command)||Activates a mode in which you can type any key to get JAWS to announce its function at the current location.|
|space||The Describe-Next-Key function: Press just before pressing another key or key combination to hear its function without having to enter help mode first.|
|JAWSKey+H||Display in the JAWS virtual buffer a list of commands available at the current location.|
|tab, shift+tab, and enter||Move among and execute, respectively, the commands available at the current location.|
|control+tab and control+shift+tab||Jump to the first or last command available at the current location.|
|' (apostrophe)||Switch to another key map. This key actually puts you into a map whose purpose is to choose a map though, so the above help facilities work here to help you find a map to use.|
|JAWSKey+t||The Where-Am-I function: Announce the current map name and location.|
|.||The Context key (not available in all maps): In maps supporting it, goes to a context map for the current location. This is, for example, a way to get the MSAA Window or Client object from a window handle.|
|;||In maps supporting this feature, cycles among related maps for the current type of location. For example, ; cycles among Cursor Navigation, Pixel Navigation, and other related maps that address physical screen locations.|
|m||The BX Mark system: This goes to a small map used for setting, clearing, and jumping to marks. A "mark" is a location (a window, an MSAA object, an HTML object, etc.).|
|Windows+letter||A shortcut for jumping to a specific mark. For example, if you created mark a earlier, Windows+a will return to it. Jumping to a mark will also return you to the map you were in when you created that mark.|
|alt+e||Brings up an edit box in which you can type a JAWS function call with parameters and press Enter to run it immediately. Nested function calls will not work.|
|JAWSKey+C||Cycle through available cursors. Useful in maps where the normal PC and JAWS cursor commands are not available.|
|"||Object type name: Press once to hear the name of the current object's type, assuming the current location involves an object, and twice to hear its interface name. This is an advanced feature and may require TLBInf32.dll to be registered.|
|Escape||Exit a nested key map if one is active, returning to the one active before it was loaded. This is a way out if, for example, you hit an apostrophe (map switch) by mistake and don't really wish to switch maps.|
|Alt+c||Starts and stops text collection. Type once to start text collection,
then use one or more BX commands that produce collectable output (most
output is collectable, but the output of
|Alt+m||Cycle through the three possible MSAA modes available in JAWS. The
first press of this command simply announces the current mode; subsequent
presses (without other intervening commands) will cycle through the
remaining modes. The MSAA mode can have an effect on the output of numerous
JAWS commands, notably commands like
A more recent feature of BX is the so-called "BX Quick Key," sometimes
also written as "QuickKey" (without the space). This is a key that
provides access to a miscellaneous set of functions without requiring
BX itself to be activated first with JAWSKey+space. By
default, the Quick Key is not set up; but it can be set up simply by
assigning a key to the
BXQuickKey script. The author
prefers to assign the right bracket key (]) key as the BX
To use the Quick Key, assign a key to the
script, then restart JAWS once or reload all scripts and
configurations, which can be done in sufficiently new JAWS versions by
typing Ctrl+Insert+Escape or in any JAWS version by compiling
any script using the JAWS Script Manager. Once the key is
functioning, tapping it will cause JAWS to say "BX" and wait for
another key. The Tab and other help facilities work here
just as in BX itself to help you find commands and features of
As of this writing, the built-in Quick Key functions fall into the following categories:
Warning: The Quick Key functionality itself is stable, but the specific available commands and their current layout are rather fluid and subject to change. The text management commands in particular could use rethinking.
BX is capable of generating, to clipboard and to JAWS virtual view, a
log of event calls. This can be very useful in determining which
events fire at certain times or in response to certain actions.
At this writing, about 230 event and
say functions can be
To use this feature:
Some applications may, such as during a login process, relinquish and then retake focus, causing any loaded scripts to unload and then load again. If this happens while events are being logged, the event logging will stop and the event-logging scripts will be unloaded and not reloaded automatically. You can retrieve the logs accumulated up to the time of focus switch out of the application by repeating steps 2 and 5 from the above instructions (i.e., load the event-logging scripts and type JAWSKey+E once to view the already-accumulated log). It is currently not possible to log events safely through the out-of-and-back-into-application focus switch.
The event logging system supports customization through callback functions. These functions should reside in the custom default.jss file that loads BX itself, so they will not go out of scope when the event-logging code is loaded. Code in these functions should execute quickly when possible, as these functions may be called very frequently and rapidly.
To filter what is included in the output, write a
logcallInclude function like the following:
int function logcallInclude(string call) ; Call is the full function call being logged, e.g., "WindowCreatedEvent(12345)." if call == "keymapchange" || call == "keyPressedEvent" then ; Do not log these events. return False elif logcallLevel("FocusChangedEventEx") > 2 then ; Log FocusChangedEventEx and whatever it calls directly, ; but do not log any deeper calls stemming from this event. ; (level 1 is the event itself, 2 is a direct call from it, etc.) return False elif stringContains(stringLower(logcallName(call)), "highlighted") then ; Do not log SayHighlightedText or SayNonHighlightedText. ; logcallName() returns the name from the call without the parameters. return False endIf ; Log all other events being traced. return True endFunction
To add extra log lines for specific events, write a function like the
Any return value, which may contain multiple lines, will be included
and properly indented in the log output.
This example adds two lines below each original
WindowCreatedEvent call (two lines because of the
\n in the
string function logCallExtra(string call, int isReturning) ; Call is the full function call being logged, e.g., "WindowCreatedEvent(12345)." ; IsReturning is True if this is a function return and False if it is the original function call. if isReturning then ; No extra log lines for returns, just for original calls. return "" endIf if call == "WindowCreatedEvent" then ; Log useful information about the window being created. var handle hwnd let hwnd = stringToHandle(stringSegment(call, "(,", 2)) return formatString("Class %1, name %2, IDString %3\nOwningApp %4, type %5 (%6)", getWindowClass(hwnd), getWindowName(hwnd), getControlIDString(hwnd), getOwningAppName(hwnd), intToString(getWindowTypeCode(hwnd)), getWindowType(hwnd) ) endIf ; No extra lines for any other events. return "" endFunction
These are uses of BX that go outside the norm.
Standard list and combo box controls support MSAA and thus make their contents available even when not displayed on screen. This is also true of standard HTML controls. This can sometimes be useful, as in the following examples:
BX can be used to find and monitor this type of activity as follows:
Here are documented the origins of and plans for BX.
BX has its beginnings as far back as 2001 in a lot of code snippets I tinkered with as I found time. I kept trying to figure out a way to reduce the amount of time I had to spend testing things for scripting projects, but I couldn't come up with a satisfactory interface just by creating scripts., because the interface invariably became unwieldy. I wanted a way to redefine any key on the keyboard dynamically, and also a way to specify what each key should do in a more concise way than by writing a new script for each case. I made several attempts at both problems, one of which used the JAWS virtual buffer and allowed keystrokes to add to it dynamically; but I was still not happy with the results. The virtual buffer idea made me realize I also needed a system that had absolutely no effect on what was in focus or on the results returned by all the JAWS scripting functions. Using the virtual buffer violated this requirement.
In late February of 2003, I finally met with success and began collecting code snippets into a coherent system. Predicting, accurately as it turned out, that some of my coworkers might also want to use the result, I named the budding tool Bart Explorer and sent a copy to a few coworkers for them to play with. (This name is where the name BX initially came from.)
Although I created much of BX in my spare time and outside any project under company direction, I actually thought it might one day become either a part of JAWS itself or a Bartimaeus Group company product for commercial distribution. Neither happen, although one or two binary copies were actually sold. Because of this thought though, because I had such a complete lack of experience in the legal arena and did not know how to craft an appropriate license agreement,, and perhaps mostly because I knew the tool suffered from a profound lack of documentation, I said little of the tool's existance to people outside the company. I did, however, keep developing it regularly and kept my coworkers apprised of my progress, adding features as I found need for them and occasionally in response to coworkers' requests and suggestions. At some point I realized I was also leaving a trail of BX installations behind as I went from site to site scripting for various companies and agencies, because I never scripted without it and found it decidedly inconvenient to have to uninstall and reinstall it on each visit to a site (BX at that time had no installer).
BX first went officially public on September 11, 2007. Shortly thereafter, and to my surprise, a link to it appeared on a prominant Freedom Scientific web page. The public release had no other noted significant impact however, possibly due to the aforementioned profound lack of documentation.
I intend to keep using and developing BX just as I have been, in response to needs and suggestions I receive. In gratitude to the company that helped and encouraged me to develop BX, which has been known as Bartimaeus Group, then BART Group, and now SSB BART Group, I intend to continue shaping BX based on company and project needs.
I would like to thank Victor Tsaran for his constructive input in the
very early days of BX's creation, and for writing and allowing
Bartimaeus Group and me to use a Nullsoft installation script for it.
I also thank Jonathan Avila for suggestions that guided some of BX's
development and, as he was my manager for BX's formative years, for
encouragement to write it and permission to work on it from time to
time between projects at the office.
Chad Foster also contributed some ideas while he worked with us, for
which I am greatful.
Beyond current and former BART employees,
Michael Damian Curran, also known just as Mick, deserves appreciation
as well, for contributing one major idea to BX, that being the irregular-looking
GetObjectFromEvent to retrieve MSAA objects directly from
window handles (I saw that his JFWTechnical scripts did that).
I could try thanking all the companies and individuals who, in the
course of my doing scripting both on and off the job, caused me to
think of or need various specific BX features; but the list would be
long and the time to pull it together even longer. I will just say
that it was the widely varying character of my scripting projects over
the years that caused so much to happen to BX.
Last but certainly not least, and in the spirit and style of Larry Wall, author of the Perl programming language among other major public offerings, I wish to thank the Author of my story for prospering the work of my hands.