This Technical Note discusses how your applications can be compatible with Universal Access software.
Changes since July 1991: Added caution against reading the keyboard with interrupts disabled.
Universal Access is the name given to software components designed to make Apple computers (in this case, the Apple IIgs) more accessible to people who might have difficulty using them. The Apple IIgs is very dependent on graphic objects, a keyboard and mouse; not all people can use these things very easily.
There are several components to Apple's Universal Access software:
Universal Access generally works by replacing Apple IIgs toolbox functions. For example, CloseView patches QuickDraw so you do not draw to the actual screen, but to another buffer that CloseView can then magnify. Video Keyboard patches the Window Manager so that its keyboard window is always frontmost and fully visible (and accessible). Easy Access uses the ADB tools and the Event Manager to alter the way the hardware responds.
Since Universal Access changes the way the tools behave, your applications do not have to work very hard to be accessible to a broad range of physically challenged people. Just by following the rules, you have an accessible application. There are, however, a few guidelines you should keep in mind when designing your programs to make them as accessible as they can be.
Video Keyboard can also be dragged in front of modal dialogs. If you are in the habit of using QuickDraw calls to draw items in Dialog Manager modal dialogs instead of creating custom dialog userItems, Video Keyboard users can drag the keyboard window in front of your dialog and erase the items (since the only items redrawn are those redrawn by the Dialog Manager's update routine). You can easily test this in all of your dialogs by obscuring each dialog with the Video Keyboard window a piece at a time, then moving Video Keyboard away, to be sure that all areas are completely redrawn.
Let's say, for example, that you have a custom text item that changes between invocations of the same modal dialog. You might choose to draw the text yourself with LETextBox2 after creating the dialog with GetNewModalDialog but before letting the Dialog Manager handle events with ModalDialog:
phx ; port: hi word from GetNewModalDialog pha ; port: lo word from GetNewModalDialog _SetPort lda OurText+2 ; pointer to text to draw in modal dialog pha lda OurText pha lda OurTextLength ; Text length pha pea OurTextRect>>16 ; Text rectangle pea OurTextRect pea 0002 ; Text justification (2 = fill) _LETextBox2
To be Universal Access-friendly, you would, instead, implement a userItem routine like the following:
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DrawDialogText ; ; DrawDialogText draws text pointed to by OurText into the Dialog. ; This userItem routine is called only by the Dialog Manager, ; when it's implementing/updating the dialog. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lda >OurText+2 ; pointer to text to draw in modal dialog pha lda >OurText ; (long addressing: data bank unknown) pha lda >OurTextLength ; Text length pha pea OurTextRect>>16 ; Text rectangle pea OurTextRect pea 0002 ; Text justification (2 = fill) _LETextBox2 lda 1,s ; get return address sta 7,s ; move to proper location lda 2,s ; above input parameters sta 8,s pla ; move stack pointer up pla ; to new return address location pla rtl
It will be called as a result of adding a template item like the following to the dialog template (note use of Item Value for the text length, since template Value fields are not used by userItems):
TextTemplate dc.w 3 ; ID OurTextRect dc.w TTop,TLeft,TBottom,TRight dc.w UserItem+ItemDisable ; Type dc.l DrawDialogText ; Pointer to our userItem ; routine OurTextLength ds.w 1 ; Text length (cheap place ; ; to put it) dc.w 0000 ; Item flag dc.l 00000000 ; Item color
Note that this is a simple example of a custom item routine; if you really had custom text that changed from invocation to invocation, you could use the existing Dialog Manager ParamText and longStatText2 item mechanisms.
To find the screen location, look at the ptrToPixImage field in a grafPort after calling OpenPort (or in your window's window record after NewWindow). The image pointer gives the correct location of the screen.
Assuming the current port is on screen, the following code finds the ptrToPixImage value:
pha pha ;made space for port pointer _GetPort phd ;save direct page location tsc tcd ;port pointer is now at 3..6 on direct page ldy #4 ;offset to high word of ptrToPixImage lda [3],y ;got high word tax ; in X ldy #2 ;offset to low word of ptrToPixImage lda [3],y ;got low word tay ; in Y pld ;restored direct page location pla pla ;removed port pointer
The X and Y registers now contain the base address of the screen.
For these reasons you should not draw directly to the screen without first examining your window's visRgn. Do not just check for rectangularity -- your visRgn could be rectangular and parts of your window still be obscured. If you use QuickDraw for all your drawing, QuickDraw automatically clips drawing activity to be entirely within the visRgn, so this is not a problem.
This and all of the other Apple II Technical Notes have been converted to HTML by Aaron Heiss as a public service to the Apple II community, with permission by Apple Computer, Inc. Any and all trademarks, registered and otherwise, are properties of their owners.