WWDC2004 Session 424
Transcript
Kind: captions
Language: en
[Applause]
one morning I'm guy Fullerton manager
the high-level toolbox ex Elise node
hello my name is Mike anchor and I'm an
engineer in the cocoa group and just to
make things more confusing we're going
to change sides now so hopefully
everybody got a chance to see the
voice-over session yesterday and
hopefully you got a really good feel
about how important accessibility is to
Mac os10 and how powerful it can be so
in this session we're going to build on
yesterday's session and describe some of
the implementation details you need to
go through with your applications to
make them accessible we're going to give
you a brief architectural overview of
how accessibility works we're going to
talk about how to accessorize two types
of widgets we're going to tell you how
to add stuff to a standard widget
augment it with a few extra things you
might want to augment it with and then
we're going to tell you how to
accessorize a custom widget that derives
from one of our standard ones and
finally we're going to have a long
section on troubleshooting and giving
you tips and tricks for accessorizing
your application so I think Mike's going
to start out with the conceptual
overview okay so before we get into the
details on what you need to do to make
your applications work with
accessibility I'm going to give you a
little bit of background on the
accessibility API so when we talk about
the accessibility API s there are really
three things to consider first there's
the accessibility api's themselves and
in this slide they're shown with the
green box and these are the AP is that
we introduced back in Jaguar and that
assistive apps use to examine the user
interface and interact with other
applications on the system the second
part of the story are the assistive apps
themselves and those of you who went to
session for 24 yesterday got to see a
prime example of an assistive app which
is voiceover and the third part of the
story are the cocoa apps from the carbon
app which the assistive apps you know
examine and that's what we're going to
be focusing on today specifically
what you need to do to make sure that
your application works properly with the
accessibility API now one thing to bear
in mind even though we talk a lot about
voiceover as being a prime example as an
assistive app nothing in this
presentation is specific to voiceover
the things you do here are going to
enable your application to work with all
kinds of different assistive apps that
have been developed for the macintosh OS
now this slide is an abstract
representation of an assistive app
trying to examine the user interface of
either a Coco a4a carbon app and the
question marks show one of the key
design problems that we had to make a
decision on when developing these api
how are the applications going to
represent their user interface to the
assistive app now an obvious choice
would be to use the natural way each
application at implemented objects so in
a Coco app that's NS windows and its
control and for a carbon offsets window
rest and control rep but the problem
with doing it this way is it puts an
extra burden on the assistive apps you
have to do twice as much code you have
to have one set of code that knows the
cocoa objects and then you have to have
another set of code that understands the
carbon objects and the situation only
gets worse if we introduce other
frameworks into the mix
so in this slide we outline our solution
and the basic way we represent the user
interface is through something called a
UI element everything's a UI element
windows or UI elements buttons or UI
elements even the application itself is
the UI element so both cocoa laps and
carbon apps are going to return to the
accessibility api's their UI represented
as a bunch of UI elements so to
summarize a UI element is an abstract
object we use to represent a part of the
user interface and the applications
represent themselves as a whole
hierarchy of UI elements assistive apps
will look at a UI element and they can
in it which has attributes and the
sisters apps can use these attributes to
get information about the UI element for
example its title or its value or could
use the children attribute in order to
start traversing the hierarchy of UI
elements and UI elements also support
actions and these are what assistive
asked use to actually drive applications
for instance to press a button or to
increment a slider so to sort of bring
these concepts alive guy is going to
demonstrate one of our tools called
accessibility inspector and do a live
demonstration of inspecting one text
edit yeah so if I could have the second
computer please
perfect thank you all right so what I
have running here is text edit and I've
got a document open that has just a
little bit of text in it and I'm going
to run the accessibility inspector
application which is part of the
developers tools install and when i run
the accessibility inspector you get this
floating window that describes whatever
the mouse is over now by default the
font size is really small and I can see
it's fine but something tells me you
won't be able to read it unless I make
it bigger so that should be ok so now as
I move my mouse around the screen and
point at different things the
accessibility inspector updates with
information about each of the elements
that I roll over so if i stop on this
text area for example you can see the
hierarchy that contains that text area
it's inside the application textedit
inside the window document inside a
scroll area inside a text area and then
it's a link as you can see in the
attributes section there's a number of
attributes that supports it's gotta roll
ax link has a role description which
looks like it's a bug to tell you the
truth it's got a sub role you've got a
parent various other pieces of
information about it and of course the
attributes that an element supports
varies based on the element so if i go
and hover over a push button you can see
a different set of attributes and even
some actions in this case one cool thing
that the accessibility inspector can do
is lock on to a UI element so if i press
f5 you see the text in the inspector go
red and you see another floating window
appear and now when i move them out the
text in the inspector no longer updates
so I'm locked on that push button which
lets me do a couple really cool things
the first thing is I can potentially
manipulate other parts of the UI with my
mouth without disrupting what the
inspectors showing but the second cool
thing I can do is potentially go up and
down the containment hierarchy in the
second window that shows up there's a go
to menu and I can choose other things
from within that go to menu I can go to
the buttons parent which is the
Preferences window as a whole now this
is really important if you need to get
to an element in your application that
doesn't really have much of a visible UI
widget that you can point at but you can
point to some child of that so if you
can point to a child of it you can
continually traverse up the parent
hierarchy until you get to the element
you want not only can you go up but you
can also go down
so now that I'm looking at the
Preferences window element I bring up
the go to menu and I can see that
there's a list of children so I can go
to any of these groups and from within
those groups going to the children of
the group and so I can find all kinds of
different things out about elements so
let's go ahead and get back to the
button real quick I want to show you
another cool thing you can do so also in
this secondary window there's a pop up
with all of the bring this up a little
bit all of the attributes that the
button support so you can choose one and
it changes the little value in the text
area here to represent the value for
that attribute now this doesn't show it
really well and see if I can find one
here if I lock on to a text field indeed
I am in a text field and I choose the
value actually when I pop up this menu
you can see that there's a w next to the
ax value attribute that means the value
is writable so now when I choose value
from the pop-up you can see that the
text is now writable inside the
secondary window and I can change that
to a tee press set value and you see
that actually updates in the interface
another cool thing you can do with the
secondary window is closed the highlight
checkbox this is an easy way that you
can test to make sure the size and
position you're returning for an element
is correct so I'm I've locked on to this
text field and when I click highlight
you get that pink window that shows what
your highlighting are the bounds of the
thing you're highlighting and in fact
highlight sort of stays on once you've
clicked it you can click it again to
turn it off but the cool part about that
is you can hit f5 again to unlock go
point at some other object and it now
highlights that other object so it's
really good for testing those kinds of
problems bounds related problems let's
go back to the button again because
there's one more thing I want to show
you don't need to highlight anymore all
right so i hovered over the button and
it's revert to default setting and you
see that I'd already changed the window
with 275 so I've already varied from the
default another thing in the secondary
window is a set of actions that an
element supports buttons support a press
action because you can press button and
the cool thing about the palette is I
can perform that action and when I
perform that action you see the revert
button actually flash and then the
window with gets updated back to 75 so
accessibility inspector is a really
powerful tool probably probably the most
common tool you'll use when you're
rising your application to test that
you're doing things correctly so I'd
like to go back to slides now
ok
so that's a brief overview of one of the
tools so now it's time to dive down into
the nitty-gritty of how you can sort of
implement this in your own application
but some of you are probably wondering
how hard is it going to be so we have
this fancy little chart here that can
illustrate that for you okay colors and
jokes aside the basic principle is the
more standard stuff you use the far
easier it is to become accessible the
more custom stuff you use the more work
you have to spend making it accessible
and that's just you know regardless of
whether your cocoa app or a carbon app
for example if you're a modern Coco app
or a modern carbon of that app that's
based on HIV you and compositing it's
really really easy to accessorize that
application but most apps can't use just
the standard system widgets right most
apps have a few custom things and so
those apps you know they'll need to do a
little bit more work to accessorize
those custom widgets and that's not too
tough either the real problem case is
when you're at the far other end of the
spectrum and you're a completely custom
app doing all kinds of old stuff let's
say you're on a really old class library
and you ported your application to 10
and made it run but it's not using the
very modern technologies of either
framework well that's going to be really
challenging to accessorize because
you're pretty much going to need to add
accessibility information to everything
in your interface except for the few
standard widgets you use so the take
home is really maybe this is the time
not just to accessorize but to adopt
other Apple technology like a chive you
in your application sure it's going to
take a little bit of effort to adopt a
chive you but that effort is going to
pay off in two ways you're going to get
a bunch of other benefits from a chive
you and of course it's going to make
your accessibility implementation a lot
easier as well you should seriously
consider that when you're accessorizing
your app okay so I showed you some
attributes in the inspector but let's
talk a little bit more about some of
them so fundamentally attributes provide
information to an accessible application
about the elements in your app and an
assistive application will want to make
four main requests of your app with
respect to its attributes given an
element and assistive app needs to know
what attributes is that element support
it might want to get the values of
certain attributes of course it'll want
to see a fine attributes edible and if
it's edible it's going to want to set
the attribute now all of the attributes
that we sell the standard attributes can
be seen in the H I services header I put
on the slide
but when you open that header don't be
scared by the sheer quantity of
attributes in there there's a lot that
dozens and dozens and dozens don't make
don't let that make you think it's
really hard to accessorize most elements
only support a small handful of
attributes as I was showing in the
inspector you know push buttons have
about ten various other things might
have about fifteen so it's really not
that tough so don't don't feel daunted
when you open up the header so I want to
talk about some of the very most common
attributes that you're going to have to
use and you're going to come across the
most fundamental attribute is the role
every element must have a role a role
describes an element's basic purpose and
in fact a role is what an assistive
application uses to determine how it
should present this interface to the
user in some other way voiceover for
example when it sees a button it knows
the buttons that certain properties
associated with it and it knows it can
communicate with the user in a certain
very specific way about the button
however an assistive application can't
use that role as sort of a spoken
description to the user about what the
the element is because mainly the role
strings are prefixed with ax and they're
just there to be sort of switched on at
runtime by the application so if an
assistive application wants to present a
human readable representation of that
rolls purpose it uses the role
description attribute which is a
localized string that can be spoken to
the user or shown to the user in some
fashion now another really common
attribute is the title attribute the
it's generally obvious when to use this
you know the don't apply button up there
its title is don't apply the check box
is in the other window the titles right
next to those are pretty easy but the
thing to realize is if the title
attribute is only for visible text don't
try to put a title in place for a push
button that just has a picture on it but
doesn't make sense the assistive
applications assumed that if there is a
title attribute there is visible text
associated with that element if you have
an icon button there are other ways to
provide information to an assistive app
and we'll cover that a little bit later
another really common attribute is the
value attribute again this is
self-explanatory for the most part but
there's a really cool aspect and that is
that unlike a lot of other attributes
the value attribute can be of just about
any type
of course the type depends on the role
of the element you're talking about the
check boxes on the furthest back window
there on the screen they are going to
have a value that's a number and it's
going to be either 0 or 1 the based on
whether the checkbox is checked by
contrast the text field on the terminal
info window its value is the text inside
the field and that's going to be a CF
string ref generally possibly some
slightly different representation but
again it's two completely different data
types that that depend on the role of
the element you're talking about now as
mike said elements are hierarchically
organized within an accessible
application you've got a application
that has as children probably a menu bar
several windows and each of those
windows are going to have child elements
their various views and buttons and
things like that within the window so
every element has a parent so that's not
technically true there is one element
that doesn't have a parent but that's
that's something that we write so you'll
never need to worry about than here in
your applications for your purposes just
remember that every element has a parent
the children attribute however are not
necessarily supported by every element
children attributes on the children
after be only needs to be supported for
elements that obviously contain other
elements a window is going to have
children is going to be the views within
the window but a push button for example
doesn't have children it doesn't make
sense because the text in the button is
already represented as its title so mike
is now going to take you through the
easiest case of accessorizing an
application okay so this guy said if you
stick to the standard widgets you're
going to get most of your accessibility
for free and in fact all the attributes
guy was just talking about are things
that the framework you know either cocoa
or carbon are going to provide for you
and there's lots of other attributes
like the position and size which you
didn't go over that the frameworks are
going to provide for you but there are
some things that we can't figure out and
the example guy gave of a graphical
button the button that just has a
picture in it is is one case where we
cannot figure out what that button mean
and that's what we're going to discuss
in the next few slides a handful of
attributes that you're going to need to
implement because there's
it's not enough information for us to
provide them at the framework level so
the first is for lack of a better name
I'm going to call these instance
attributes and that's because you have
to go in by hand and for each instance
of these kind of widgets you're going to
have to provide this sort of information
for us and the first one I want to talk
about is the description now the
description is a string that describes
what a widget does but it doesn't
describe what the widget is now let me
reiterate that it describes what the
widget does what the widget is is
covered by the role and so for instance
a button is known to be a button because
of the role attribute in F this button
happens to cause the text to be left
aligned that's the information we want
to be provided by the description
attribute so if we take a look at the
DVD controller we can see that a lot of
the buttons there don't have any text
and so in this case the assistive app is
going to rely on you to provide a
description of what they do otherwise
all it's going to know is that this is a
button and then the users you know can
will be able to press it but they'll
have no way to figure out in advance of
pressing it what the heck is going to do
now even buttons that have titles are
sometimes hard to figure out take a look
at the calculator all the buttons there
have a title but a good percentage of
those titles aren't particularly
informative so for instance you know the
MC button or the period button you know
if you don't provide a description it's
going to be pretty mysterious as to what
these buttons do so in case all this is
a little bit confusing all these
attributes let's just go over an example
let's take the MC button in the
calculator that button is going to have
a role the role is going to be a X
button and that's provided by the
framework the button is also going to
have a role description
and that's going to be button and this
is a human reasonable string it's going
to be localized and again we provide
that in the framework it's going to have
a title and the title is going to be a
two character string the letters MC and
once again that's provided by the
framework and then there'll be some
other attributes like its position in
size that are also provided by the
framework but that's it and we're going
to rely on you guys to go in and give
that but in the description which should
be a string something like memory clear
the next instance attribute I'm going to
talk about is the title UI element
attribute now recall that we were just
we mentioned before that the title
attribute is a string that a widget
actually displays and take a look at the
the lock button the string next to it
isn't part of it so the lock button will
not have a title but yes there's this
piece of static text next to it the
decided user can figure out serves as
the title for that lock in order to make
this this relationship available for
assistive applications you need to
implement the title UI element attribute
and its value will be a reference to
another element that serves as a title
in this case the piece of static text
next to it another common case our text
fields on the screen I have a text field
that contains the text Apple and this
text field has no title at first you
might think oh its title should be Apple
when you think about controls the value
is the part of the control that changes
as you manipulate it and when it comes
to a text field the part that changes as
you use it is the string inside so
that's the value not the title now just
string the string next to it is a
separate widget and that serves as its
title but the only way in assistive apps
going to know that is if you once again
go in and set the title UI element
attribute for that text field to point
to that piece of static text
there's a related attribute called the
serves as title for UI elements
attribute and this is the back pointer
and this could be useful if an assistive
app allows the user to say mouse over a
piece of text and it wants to decide
well what what purpose does this text
serve in the user interface if it has
they serve this title for UI elements
attribute then I'll know that this piece
of text is the title for this list of UI
elements and this value the value for
this attribute is an array because a
single piece of text often serves as a
title for multiple widgets another very
important instant ass instance attribute
is the linked UI elements attribute the
common model and user interfaces is to
allow the user to make a selection from
a list or a table or a radio group and
then another part of the user interface
reconfigures itself to reflect that
selection now just because you make a
selection in one spot and other widgets
changed there's no way for us the
frameworks to sort of detect this
relationship and that's why we rely on
you to give the list or the table a link
UI elements attribute that shows us that
the selection in this object affects
these other widgets
now the link UI elements attribute is an
array because often this collection
affects the whole bunch of other UI
element and it might look like in this
slide that that's the case here but it
really isn't in this case the array
would contain just one element the tab
group now if the tab group weren't there
then it would contain the whole host of
elements you see on the screen and I
think in most cases you'll find that the
the linkage will be to a single sort of
grouping UI element in the last instance
attribute I'm going to talk about is
specific to sliders another common
practice is to create a slider and then
create separate either pieces of text or
graphics that annotate the various tick
marks and once again these are not part
of the slider so there's no way for the
frameworks to detect this relationship
so we rely on you to provide a label UI
elements attribute which is an array of
the elements that annotate the tick
marks and that's only part of the story
because the other thing you want to know
is well what what value does each
annotation correspond to well in order
to discover that you need to give each
of those elements a label value
attribute which contains the
corresponding slider value setting
alright so now we've talked about some
of these instance attributes and the
next question is well how do you go
about implementing them and before tiger
the answer was you had to had to
actually subclass the widget in order to
add these attribute and that's that's
pretty cumbersome and now that we're
trying to encourage developers to add
all these attributes it's not a really
nice story to say well you have to you
have to create a subclass for every whit
in your in your user interface just in
order to provide description so in Tiger
both cocoa and carbon have introduced
ati's that allow you to take a
particular instance of a widget and
associate a new attribute with it and
that's what we're going to talk about in
the next few slides first I'm going to
discuss how it's done in Cocoa guys
going to cover how it's done in carbon
and then we're going to give you a sneak
preview of how this can be done in ib
interface builder without writing any
code but that doesn't quite work yet in
your tiger seed so that's sort of a
future direction but the slides were
going to present next on how to do it in
code work today with your tiger seed so
I'm going to start by just giving you
the API in Cocoa that performs this it's
called accessibility set override value
and you passed it the attribute and the
value you want it to have and that's
pretty simple well it's not quite that
simple the first thing is even though
this is a method on nsobject you can't
use it on any old NSG object you can
only use it on objects that implement
the accessibility protocol and the
second the second point goes back to it
another thing I alluded to earlier one
of the big advantages of the whole
scheme of UI elements is that we squish
some extraneous detail out of the out of
the natural representation and we don't
expose it to accessibility so for
instance in a cocoa app there's a button
on the screen actually consists of a
button object and inside is another
object called a button cell and the real
meat of the
button is implemented in the button cell
and that's all this exposed to
accessibility so if you set the
attribute on the outer button not the
button cell it's going to have no useful
effect because the button set of the
button is not exposed to accessibility
only the button cell and if that sounds
a little confusing I would like to refer
you to the app kit release notes and
there's a long section that's written
about how you know these sorts of God
shoes and another thing that might cause
some confusion is the fact that there's
a couple of these methods that both have
the word set and attribute in their in
their name now there's an entirely
different concept in accessibility and
that is allowing assistive apps are
allowed to set the values of certain
attributes so for instance that
assistive apps might want to move a
window and it does this by setting the
value of the position attribute but
that's an entirely different thing than
giving the window a position attribute
the window already has a position
attribute and the giving it of it the
the method I'm describing here allows
you to add attributes to thing and it's
something you do whereas the the method
accessibility set value for attributes
that's where the assistive apps come in
and they set the attribute values for
the attributes where you allow it so
here's a bit of example code on how you
might accomplish this in a Coco app
we're going to give a description to a
back arrow button that otherwise has no
text associated with it the awake from
nib method is called when the files
owner on the files owner when this
widget is loaded so that's a natural
place to try to do this and notice the
first thing we do is we extract the
proper thing we express the button fell
out of the button and then we make our
call accessibility set override value we
pass it a string back in the name of the
attribute we want to set and that's all
there is to it and now guys going to
explain how this works in carbon so
before I dive into this new AP
we added for Tiger I want to cover one
other detail and that's the notion of
what is exactly accessible in carbon as
you can see this api's first parameter
is an H I object graph H object refs are
the key to accessibility on carbon nehi
object ref and controls windows menu
there are all H I objects each of those
constructs is inherently accessible in
fact controls windows and menus already
have a bunch of built-in accessibility
infrastructure in them that's how we're
going to provide all the default default
attributes so you'll see some of our
accessibility API take H object and
essentially what you can do is you can
take any window wrap or control ref men
us cast it into an H I object and just
call these api so the equivalent API to
what Mike just showed is called H I
object set auxiliary accessibility
attribute well I actually got that out
first thing you need to pass in is the H
I object and on the identifiers that
represents the element you wish to add
the attribute to then you give it a name
and you give it the data you want to
associate so again same sort of example
there's a back button in your interface
but it just has an icon on it no text
you want to give it a description here's
how you do it let's say you happen to
create your window from a nib you can
call a chive you find by ID to look up
your back button now you've got a
reference to your back button then you
call this new API pass the back button
and zero see how I have casted the back
button which is normally an HIV ref into
an object ref pass that back button and
an identifier of 0 which says hey Owen
will associate some data with the
element that represents the whole button
you give it the attribute you want to
add and you give it the data you want to
add which is the string back and once
you've done that the accessibility
infrastructure and carbon will take care
of the rest for you automatically it's
really pretty cool so now I'd like to
bring up Aaron Haney to give you a brief
demo of interface builder and how it can
make your lives a lot easier or we'll be
able to make your lives a lot easier
thanks guys ok so this is very similar
to the demo I did yesterday during the
voice-over session but i'm going to show
a few additional things what we have
here in xcode is a small hello world
style app that just has a couple of text
fields in a button and right now it
doesn't have anything other than the
default accessibility information in all
of the UI elements
as guy in like say this is you know a
lot of the standard widgets will give
you a lot of stuff for free but it
doesn't quite give you everything so let
me just show you real quick what happens
if you look at this with an
accessibility application interface is
an active press control option and six
to learn more then we'll have
application window accessibility demo on
to in a text field now you can see it's
just saying at a text field and it texts
few and down here okay that's not very
descriptive it tells you what kind of
control it is but it doesn't say
anything else about it let me turn this
off before it gets too chatty so to fix
this we can open the nib and you'll
notice in the info window there's an
extra item accessibility so let's select
these to edit text field now this is a
case where we don't want to enter a
title for this you ilm in itself what we
want to do is link it to another UI
element and have it used the title of
the one that it's linked to so what we
can do is just ctrl click and drag and
create a connection and select title UI
elements and connect that up now let's
do the same thing for the last name
field
and while I'm here I'm going to take a
look at this button which is an image
button a fairly common case as I
mentioned a title is for a case where
there's actual text on the control and
in this case there is no actual text so
a title is inappropriate what we want to
do is add a description so we'll go to
the description field here and type in
some text now the fact that it's a
button comes out of the role description
attribute so you don't want to put
button in the field because then it
would read ok button button so we just
want to put what you know just the
description of the control itself not
what kind of control it is so let's try
this again
spoke on interface with an active press
control option x6 to interface builder
applications window accessibility demo
on to first name and a text field and
there it it last name in a text field
okay okay so now it's just a little bit
of work in interface builder we've added
accessibility to this small hello world
application now a couple of other things
that I want to show you is a an
accessibility inspector guy already
mentioned that in the locked view let's
lock on one of these text fields and
we'll highlight it just so you know
which one I'm locked on okay the go to
menu can be used to transverse the
parent-child hierarchy oops I shouldn't
move that while it was locked I can hit
refresh refresh where's the Refresh
right below the pop-up okay you can also
go to any linked elements such as the
title i own and now you can see it jump
over to the first name field and from
now on whenever I update the text in
that static text field it'll
automatically get picked up as far as
accessibility concerns the title of
these edit text fields will be the same
as the title of these static text fields
next month
so that's it now we want to emphasize
that their support that's on the CD DVD
is incomplete this is just to show you
the direction that we're moving in we
advise you to not use it as it is right
now we hope to get that addressed as
soon as possible anyway this is where
we're headed we want it to be as easy
and convenient as possible so that you
can add accessibility information from
all sorts of places including interface
builder and that's the demo thanks guy
thanks Aaron okay so now we've talked
about the easy case what you have to do
with standard widgets and we anticipate
that's going to be the vast majority of
the work that's needed by applications
to support accessibility but now we're
going to bump things up a notch and
we're going to talk about what you need
to do for a custom views and in the
example we're going to be working
through we're going to be talking about
if you created your own button class and
instead of starting from NS button or a
button ref you start from just a plain
view and guy and I are each going to
show how you do this in carbon and cocoa
and how you to give a title to this
widget and a title attribute and how
you'd implement a press action now the
first some of you might be thinking okay
we just showed you how to add attributes
can't I just add a title that way and
the answer is yes that will work just
fine and if you only have a couple
instances of your custom button in your
app that might be good enough but maybe
you're providing this class for other
people to use and wouldn't it be nice if
the title attribute came along for free
instead of making everyone implemented
or another thing to think about is maybe
it's some other attribute like the value
in your widgets a slider the methods we
just showed you take a name of an
attribute and a constant value and it's
not going to really work so well for the
value of a slider I mean I guess you
could every time the slider changes
value reset that attribute but
that's not really very elegant so we're
going to show you how to get some code
to run in order to implement attributes
and and then we're also going to show
you how to do this for action now in
cocoa there's a protocol or a suite of
methods that you implement on an object
to support accessibility and there's
four of those methods relating to
attributes and they correspond to the
four things that assistive apps can do
with attributes one of them is to get a
list of the attributes supported by a UI
element the second is to get the value
of a particular attribute the third is
to test if a particular attributes
edible and the fourth is to finally set
that value and this code on this screen
shows how you implement the first of
those methods accessibility attribute
name now here I've chosen to cache the
attribute names in a local static
variable just so i don't have to compute
them over and over again and the first
thing we do is check if the cache is
full because if it is we don't have to
do anything else that will get returned
but if we haven't computed the list of
attribute names yet the first thing we
do is go to the super class and get the
standard list of attributes then we
create a new array by adding the
attribute we want to add the title
attribute to the end of the list and
finally we tuck that away in the cache
and that's all we need to do
all right this is the code that support
returning the value for an attribute the
method name is accessibility attribute
value and the first thing we do is check
if the attribute being queried is the
attribute of interest in this case the
title attribute and if it is we return
our notion of the title otherwise we let
the superclass handle it and the last
met that i'm going to show you is the
method that handles returning whether or
not an attribute can be set and once
again we test is this the title
attribute and if so we return no because
we don't allow users to change the title
of our button and if it's not we let the
superclass handle it now those of you
who have been paying attention might
realize I said there's four methods well
the fourth method involves actually
setting the attribute and since we don't
allow the title ever to be set the code
for this method would always just defer
to the superclass so there's really no
point in implementing it so from carbon
a very similar protocol to what Mike
described in carbon accessibilities is
achieved through I think its nine
different carbon events you can install
those however you would normally install
carbon events in this example here I
happen to be doing at an H object
subclass registration time you don't
have to do it that way if you use create
custom control or create custom window
or something like that after you create
the control of the window you can call
install event handler and install your
event handlers afterwards it's all going
to work just the same so three of the
attributes sorry three of the carbon
event that we have up here are the get
all attribute names is named attributes
edible and get named attribute carbon
events again there's also an event
that's used for setting there's some
events that we'll talk about later use
for actions there's also some events to
use for hit testing we're not really
going to cover that today but there's
lots and lots of documentation in carbon
intensity H on exactly how you need to
handle these events what parameters you
need to look for parameters you take out
so let's dive into the example ok so the
same example Mike was talking about
you've got a custom view that has a
title and you want to provide that
attribute because it's not being
vided for you automatically by the by
the view system because it doesn't know
your customs you have the title so
here's what your handler forget all
attribute names might look like the
carbon event comes in you need to call
next event handler to let the inherited
a chai view implementation pre-populated
with a bunch of the standard attributes
like the size and position and stuff
like that all the stuff you want the
system to provide for you then you
extract the mutable array of attribute
names from the event and you add your
attribute to that array any return and
that lets the assistant accessibility
system know that hey there's this
additional attribute that's been added
in the next event I want to talk about
is the is named attributes edible carbon
iment when this carbon event comes in
sets the name out of the event and sorry
push the attribute name out of the event
and see if it's the attribute support if
so in this case obviously the title is
not settable so we just stuff an event
parameter any of the events indicating
that no it's not settle and then you
return let me jump back here is
something I left out of this code
example obviously if it's not one of the
attributes you support call next event
handler or return event not handle there
and that'll let the inherited
implementation provide all the right
information for it so when an assistive
application wants to query a value again
very simple extract the attribute name
out of the carbon event if it's the one
you support stuff an event parameter in
the event with the value in this case
we're stuffing the title in presumably
the title is a CF string rep and the
carbon event manager is going to do all
the right retain release semantics for
CF types
and I'm going to talk a little bit about
abstraction ok so we've shown how to add
an attribute to your custom view next
we're going to get into how to add an
action but first a little background on
what actions are first actions are very
simple things they're about
approximately what you could accomplish
with a mouse click and there are generic
things like ticker press now often
developers think oh I've got a print
button I need a print action or I have a
cancel button i need a cancel action and
that's not the case if the button it
should support the press action the fact
that this button prints can be
discovered by looking at its title or
description so don't fall into the trap
of thinking you need a lot of action in
fact there's less than 10 actions
defined and I don't anticipate that list
growing very much the assistance the
accessibility API support three basic
operations with actions first you can
ask a UI element for a list of all the
actions and support and in most cases
it's the empty list or just one thing
then you can ask just to get a use human
readable string for a particular action
that fits the description and finally
you can try to perform that action now
Coco and its accessibility protocol has
three methods that correspond to those
three operations and this slide shows an
implementation of the first returning a
list of action name and it's very
similar to what you do with an attribute
first you call the superclass to get a
list of inherited action and then we
slap our action on the end of the list
and return the augmented list
this is the method it handles returning
the description for a particular action
as with attributes the first thing we do
is check is this is this action the one
of interest because if it's not we'll
let the super class handle it but if it
is we're going to call the NS
accessibility action description
function and this is something new and
Tiger before before tiger you were if
you will do to return an action
description you sort of had to look
around and say well how did we describe
the press section and you might use
accessibility inspector and discover you
know the buttons had a press action and
and then you also had to maybe guess how
might they localize that so we're sort
of taken the mystery out of that process
and giving you a function that's going
to return what our standard widgets do
for action description and I refer you
to the applicant release notes where the
functions described in detail along with
some related ones for role description
and the final method in this action
suite is for actually performing the
action and first we again we check is
this the press action that we care about
if so we do the appropriate thing
otherwise the superclass handles it and
now guys going to show what you do in
carbon so three of those nine carbon
events are pretty much identical to the
application methods for performing
actions the first one is get all action
names it's a lot like get all attribute
name so the fact you handle it the same
way you call the next event handler to
let the inherited implementation add any
name you extract the mutable array of
names and you add your new action to it
get named action description is also
simple but there's one kind of weird
catch here there is a mutable string ref
in this event you need to extract that
string rep and replace it with your text
replace the text in the string with your
text and return so that's how you
provide an action description I've left
out the code here just for simplicity of
where we are looking to see if the
action that we support and if not of
course it's going to call next event
handler
now this is the only tricky part of the
accessibility carbon event and that has
to do with performing named action but
before I kind of dive into this let me
give you a little bit of background for
why this is complex when an assistive
application is telling your app to do a
press operation that assistive
application is blocking waiting from a
response from our messaging protocol to
say whether or not the app is alive
right your app might be crashed or
tongue or in gdb or something and so the
assistive application needs to know if a
timeout has elapsed and you know it's
got to forego the attempt to press
however that need often contradicts what
actually happens in an application when
you perform a press type operation on a
button a lot of buttons will bring up
some kind of modal interface or might
cause a menu to be tracked which means
that your accessibility event handler is
not going to return right away right
it's not going to return until the users
done dealing with the dialogue which
could potentially take minutes depending
on what the dialogues for which means
that assistive application who just sent
the press requests over is going to get
a timeout and it's going to think the
press failed and it's going to
communicate to that that to the user so
now the user is going to be really
confused because they thought something
didn't work but now there's this new
interface that's showing up and it's
just a big mess so the way we solve that
mess is by a parameter in the perform
named action carbon event there is a
parameter indicating whether or not this
event was sent to your element in a cube
state now by default and just mainly for
compatibility purposes the event gets
sent to your element initially in an
uncute state we dispatch it directly
that's just the way we've been doing it
since our initial accessibility
implementation so if you see that happen
well let's go to the other case let's
say it hasn't been queued or sorry it
has been queued that's the case you want
to handle if it has been queued you can
go ahead and carry out your action in
this particular situation we've got a
button we just call HIV simulate click
which will cause the button to flash and
out all the right carbon events so your
application can respond to it and it's
safe to do it now because the events
been queued you already know the
assistive app has received an
appropriate return value saying aai was
successful but if it wasn't cute you
need to return the event for excessive
sorry event defer accessibility event
error from your handler and that
essentially is a request to please cue
this event and send it to me at some
time later because I know I'm going to
put up some potentially blocking kind of
in
that's really the only trick to it okay
so so far we've been talking about
fairly easy cases right you've got an
existing view like a push button you
just want to add a description to it or
then you've got an HIV or a nephew
subclass and you need to provide some
accessibility information above and
beyond but the frameworks offer for you
but now the hardest case is you've got
some class it's not derived from NSU or
a chive you and you have to provide all
the accessibility information for it now
we're not going to go into tons of
detail mainly because we've already
shown you how to do this in the other
example there's just some things you
need to realize the first is that if you
don't inherit behavior from our standard
views and objects you have to provide
all the accessibility information for
your objects that means all the
attributes you have to tell sighs
position everything else you saw in the
accessibility inspector you have to
provide all that you also need to
provide handlers for hit testing and
focus testing parts of the accessibility
protocol this allows assistive
applications to figure out what's under
the mouth in fact that's the key for how
accessibility inspector works it finds
the mouth position and calls an
accessibility API to try to find out the
element at that Mouse position and so if
your custom elements don't support hit
testing and focus testing there's no way
accessibility browsers going to work
with your app another thing you have a
responsibility for is sending
notifications there's a handful of
notifications it's in the HR services
headers so you can take a look there for
what needs to get sent out but
essentially it's for things like my
objects about to be destroyed or there
was some major state change with my
object like a value change well if you
are implementing an element from scratch
you need to make sure you send out those
notifications appropriately and we have
full carbon and Coco api's to do that
there we go all right so now let's talk
about some things you need to think
about when you're accessorizing your
application said it before we've said it
actually number times in this session if
you can switch over to the standard
controls you'll be much better off
because we're going to give you a lot of
support for free so again look at your
applications interface see if maybe
you're using some custom objects that
we've provided some modern equivalents
for and recent operating systems try to
switch over to those it's going to make
your applications interface better in a
lot of ways obviously it's going to meet
the latest aqua guidelines because hey
we're doing it and it's going to give
you accessibility support for free now a
very subtle point is don't invent new
stuff don't try to come up with new
rules don't think you need to come up
with new roles and the main reason is
that assistive apps won't know how to
deal with your new roles assistive apps
are designed around fairly finite set of
rules that we've already described you
know there's groups there's list and
things like that and if you invent a new
role you're essentially asking every
assistive application out there to rev
just to support your new widget so
really what you have to do is kind of
turn your widget around and think about
what your widget is a lot like in terms
of the standard widgets the best example
I can give for this is the crayon picker
in the color picker panel as we were
going to accessorizing various parts of
the system you know we got to the color
picker and we said oh wow cramps what
are these things I don't know do we need
a new role for that is it a crayon cran
role in a cran box I don't know but we
took a good hard look at this and said
no we don't need any role because really
when you click on one cran it selects
that cran and it selects all unselect
all the other crayons in the box so
really what you're talking about is a
radio button inside a radio group so
that's how we accessorized it every
kranz role is a radio button and then
the group around all those crayons is a
radio group and suddenly assistive
applications can just deal with that for
free the way they've already been
dealing with radio groups
okay so you found some part of your
application and you used you decided to
use one of the standard rules to
represent it now here's some of your
responsibilities after you do that take
a look with accessibility browser it
sorry accessibility inspector and find
some element in the system that has that
same role and make sure you support all
the same attributes assistive
applications rely on the fact that a
given role implies certain attributes
for example and actions in fact as well
for example an assistive application see
the button it knows it's got a press
action right it needs to be able to
assume that kind of thing so make sure
you support the same attributes and
actions as the standard roles now if you
run into a situation where your element
yeah pretty much fits into a standard
role but there's enough subtle
difference that you kind of want to call
it out but you don't want to force all
the assistive applications to rev to
support you you know you'd like to work
for free with voiceover well you can do
that through a mechanism called sub
rolls several sub roll is just another
attribute on an element the best example
of this are windows there's a bunch of
different types of windows on the system
we've got document windows floating
windows system windows sheets all these
kinds of things sheets was a bad example
cuz that actually has a different role
but all those other types of windows all
use the window role but we found that in
some cases assistive applications need
to tell the difference between a dialog
window and a document window so we do
that with a sub role the sub role says
oh it's a document oh it's a dialogue
and now an assistive application can if
it wants look at that several and make a
better decision about what to do with
your element but at the same time it can
keep working just like a window normally
could in that app so you don't force
anybody to rest another thing we found
is people are very tempted to come up
with a special role because they look at
a elements purpose in sort of in the
sense of their overall application for
example you might have a toolbar and
that toolbar might have a print button
on it and you realize that hey printing
is very fundamental to my application so
I really want this to be a print roll we
need to avoid that temptation mainly
because the notion is this button
print button is already conveyed by
something else we've given you a couple
of ways that that might happen obviously
that button might have a title that says
print so the user already knows it print
if it doesn't have a title you probably
put a description on it that says print
so the user already has these ways for
determining a buttons purpose so don't
be tempted to give it a new role just
because it has some unique purpose in
your application again just like with
attributes you need to use the standard
action there's a small handful of them
and they support just the most basic
mouse and interaction sorry bait yeah
it's just the most basic mouth
interaction if you're tempted to give an
element a new action see if maybe you
can't achieve the same thing by giving
it an attribute that's edible best
example of this is the Select ability of
text in an edit field right we could
have introduced some complex set of
actions so that you can set selection
here then send selection there now we
don't bother with that that gets really
complex instead there's just a rideable
attribute that is the selected text
range so the user can set that that way
now a lot of applications these days are
inherently mouse based and that means
they're not going to work real well with
accessibility right it to be to be a
true accessible application you need to
be able to unplug the mouse from your
computer and still use all parts of your
application so an interface this
entirely drag-and-drop based really
isn't going to cut it so as you're
looking at your application in your
examining its functionality see if
there's anything that's drag-and-drop
base that doesn't already have a
keyboard driven alternative if it does
have a keyboard driven alternative you
don't really have any extra work to do
but if it doesn't you need to consider
providing an alternative some good
examples of how we did that for windows
normally if you drag the window you
click with the mouse you move the mouse
to a different position and let go well
that's not going to work at it on the
mouth plugged in so to achieve that
through the accessibility API all
windows have a writable position
attribute another good example but the
finder uses when you manipulate files in
the finder a lot of people click with
the mouse drag a file from one volume to
another in order to move it or copy it
but find your ad is something a few
releases ago that allows you to copy
using the normal command key equivalents
in the menubar copy a file navigate to
some other place in the hierarchy and
paste it and that's a great way to offer
an alternative interface to doing what
was otherwise a completely Mouse based
interaction and the most cool part about
this is you're not just helping out
users of voiceover you're helping out
everybody I mean I use the copy paste
functionality and find out all the time
so really what you're doing is you're
just expanding your feature set in a way
that's going to help everyone so as we
implement our interfaces a lot of us use
grouping views and in fact some of these
grouping views that we put in our
windows there they're forced on us by
well for me you know I put various views
in your windows and Mike puts Coco views
in your windows and so the real
implementation hierarchy might look
something like this I've got a window
inside the window there's a frame view
inside that frame view there's a content
view of course there's other views for
implementation details and there's a
button and in cocoa there's even a
button cell inside that well you don't
want all that complexity to be seen by a
user of an assistive application like
voiceover mainly because a sighted user
doesn't see that complexity either when
they glance at the interface so for
accessibility purposes you want your
interface to look like this there's a
window and there's a button in it and
the way you achieve this
the notion of ignored elements there's a
carbon API called H I objects that
accessibility ignored impasse nehi
object which means any control you
really only want to use it on controls
and you can say hey ignore this control
you know I just use it for grouping
purposes and I think in cocoa the method
name is set except for their
accessibility is ignored accessibility
is ignored you can just call that with
true to mark an object as ignored now
it's similar but suddenly different
point is the concept of suppressing an
element some applications that we've
played with bring up parts of their
interface just at a certain time a good
example might be a download status
dialogue in a nap when the files done
downloading and the app wants to get rid
of that window some apps just move it
off screen you know they make sure they
move it to some crazy coordinate 10,000
20,000 so they know it's not visible to
the user well the problem with that
technique is accessibility still knows
about that window it still looks
logically visible from our API
perspective so both frameworks report
that to the user and so that's really
odd that a user of voiceover can get
this window that's off in la-la land you
want to avoid those situations entirely
and it doesn't just happen with windows
some applications move their controls
away to some crazy coordinate just so
that they're not visible to the user so
if you are one of these applications or
you see your code doing this make sure
to logically hide the object logically
hide your windows logically hide your
controls so so some one thing sometimes
people new to accessibility get these
two concepts mixed up ignored and hidden
so when something's ignored even though
it's not there from an accessibility
point of view its children sort of pass
through if you hide a view it's gone
along with all its descendants so those
are really different concepts and
usually if something's ignored it's
always ignored and whereas as your UI is
your UIs dynamics whether something's
hidden or not might change over time and
so try not to get those two things
confused
so you'll also find other cases where
you need to provide accessibility
information for an element that doesn't
have an object to back it best example
this is the scrollbar if you use the
accessibility inspector and you look at
a scrollbar sure there's a scrollbar
element there but there's also some
button elements in the scroll bar to
represent the up down and left right
buttons in fact there's buttons to
represent the page up and page down
regions and then there's an indicator
element to represent the thumb well
there's no actual view in our view
system to represent those sub components
it's all part of the the overarching
scroll bar view so if you have a similar
sort of situation in your application
the way to deal with that is by creating
objects sort of dummy objects to
represent them as accessibility objects
in carbon you create an H object
subclass potentially to do that when you
do this you're fundamentally creating a
new accessible object from scratch so
again you are responsible for providing
all the attributes and actions for that
object but there's some shortcuts you
can use to sort of get around that
requirement generally you want your the
instance this sort of done the object to
provide things like the parent and the
role but oftentimes you can either by
routing carbon events or calling methods
on the parent you can delegate some of
the responsibility to the parent code to
at least keep your code kind of
self-contained another cool thing about
this is since they're dummy objects you
don't really need to create them until
they're needed right don't instantiate
them at view construction time because
you don't necessarily know that
accessibility is on and even if
accessibilities on maybe a user's never
going to go to that scroll bar or
whatever so create the instance is only
when they're needed right maybe the
first time you're the parent object is
hit tested or the parent object is asked
for its children attribute or something
like that on the other important point
is make sure the parent does the hit
testing and focus testing otherwise
excessive sorry assistive applications
won't be able to find those those dummy
objects now mike is going to go into
some details on troubleshooting some
common problems with the excessive
accessories ation of your application
okay so yeah I have a few slides and I'm
going to talk about some common problems
that you might run into accessorizing
your app so the first one pretty simple
make sure accessibility is on
you need to go to system press and
there's a checkbox that says enable
access for assistive devices and you
need to make sure that's on now this is
not the same as turning on spoken
interface or voiceover which is an
assistive app that requires the access
for assistive devices to be on so it's
up to you whether or not you want to
enable voice over the next point is
really specific to Coco apps and this is
a pretty good habit to run into if
you're if you're implementing
accessibility on your cocoa lap and that
is to run with NS accessibility dbol
debug log level of one and I usually do
this with a command-line argument
although you could write it to your
system press and always run that way and
I'll neither confirm nor deny what
values other than one will do but if you
specify one what's going to happen is
where's the cocoa app run it's going to
see you informative error messages to
the console concerning accessibility now
perhaps what's more important than the
error messages themselves is the fact
that you're going to get a clue that
something's going wrong one thing that
both carbon and cocoa do is in when
handling requests from assistive
applications is we eat any errors or any
exceptions that are raised during the
process because we don't want an
assistive app to be able to go in and
crash some other application and because
we just eat these exceptions you may
have no clue that something's going
wrong and your apps your ass maze just
sort of mysteriously seem to not work
with accessibility so if you turn on
this option if you're you know if your
apps not working and you turn ons option
it's likely you're going to see all
kinds of spewing informing you of what
might be going wrong
now if we return to the example guy gave
of a scrollbar and has it with it five
children the up and down arrows and the
page up in the page down region and the
and the thumb and say you've gone
through the trouble of implementing
something like that and then you go over
and use the accessibility inspector and
none of the little pieces of your
scrollbar show up and that's pretty
pretty frustrating so I'm going to give
you some tips on how i would go about
sort of debugging that first off it
could be that there's something going
wrong some exceptions being thrown and
you just don't realize it so if you use
the NS accessibility debug log level of
one you know look at that console output
see if some exceptions being thrown and
that's and that's the root of your
problem alright the next thing that
might be going wrong is in accessibility
inspector you're using the mouse to sort
of mouse over the widgets you're
interested in looking at and so that
involves hit testing now in in the
frameworks we can do hit testing we can
figure out if this points over a window
or what even what view it's over but the
fact that there's a thumb in your scroll
bar we have no idea that that's going on
and how accessibility works is we're
going to tell your scroll your scroll
bar view look we think the mouse is in
you and now this is your chance to
refine that search and tell us about
some children and if you don't do that
your children are not going to show up
so that's a common mistake so the next
thing you might want to look at is if
the children aren't showing up is
actually go to the parent object maybe
you can get your mouse over that in
accessibility inspector and look at the
array of children and if you're you know
it's the thumb and the up and the down
arrow aren't even in that array well
then you've got even more fundamental
problem perhaps there's some exception
being thrown that's keeping your
children attributes from returning the
proper value and if none of that is the
problem and one other thing you might
want to look at is the is the
coordinates you're using for your hit
testing remember that the accessibility
API is all deal in terms of screen
coordinates now
the framework end we each have a slight
twist on it in carbon app you're going
to get a coordinate in top left relative
screen coordinates and in cocoa it's
going to be bottom left relative but in
either case its global coordinate so if
you're doing your computations in sort
of view relative coordinates that could
easily be what's going wrong and then
the final point of something guy already
touched on and that's the issue of
something being ignored if if the
element you're returning is ignored then
it's not going to work properly and as
an example in Co Co NS views have no
visible you know a plain generic view
has nothing to show for itself on the
screen no way for the user to interact
with it so by default views are ignored
and if your if your object descends from
NFU you need to go in there and have the
accessibility is ignore method you need
to override it to return no all right
here's a couple more problems that
sometimes arise it's important that your
that the hierarchy be sort of self
consistent and that means that you know
if the UI element says that some other
UI element is its parent if I go to that
parent and I look in the children list I
better find that child in the list and
if that's not the case then you might
get sort of weird behavior you know the
the assistive at might work in an
inconsistent way because depending on
what path it takes through the hierarchy
it may discover the child or it may not
so that's a that's a common thing to
look at and we actually have a tool that
makes these checks for you and then the
last point is once again something guy
mentioned before is sometimes people
user interfaces are dynamic and you hide
things maybe you move away off screen or
maybe you obscure it with some you know
some something that draws will opaque
white over it well if you do that the
underlying elements are still going to
be available to assistive apps and
assistive app you know they may press a
button that no user could normally press
and this may exercise code taz
your app that hasn't been tested rather
dangerous thing to be doing so you want
to hide things in a sort of proper way
either rip them out of the view
hierarchy completely or use the
appropriate method from your framework
actually hide the view in our last major
section is on performance I have a
couple slides that discuss you know how
should how should doing all this affect
the performance of your application in
the bottom line is it really shouldn't
affect the performance of your
application unless accessibility is
armed and that's the principle that both
carbon and cocoa have used and
implementing this stuff that we don't we
don't want anyone to pay any price for
this unless accessibility is turned on
and so you to help you out with that you
don't have to really worry about making
our calls we're pretty careful if you if
you want to set an attribute or you want
to post a notification you know go ahead
and do it because we're going to bail
out really quickly if accessibility is
not on and sometimes or even smarter
when it comes to posting notification if
we were actually going to check is
anyone even listening for notifications
on this object so there's no one is you
know we're going to do nothing now when
it comes to your code if you want to
optimize it this way you're going to
need a way to test if accessibility as
an R is on and you might want to use it
in fact the only way to do this is to
test if the accessibility API is turned
on using ax API enables and this is a
call from the accessibility API that you
can make and you should check it out
before you do any expensive operation
another thing to note is you shouldn't
have to worry about accessibility being
turned on while your apps running if you
make this check at the beginning of at
launch that's fine I know if you get in
there and you play around it kind of
seems the work that you can turn it on
while in apps running and things work
but that's not something you can rely on
and it's and so again and that's that's
sort of a warning the assistive app
developers to you know if you accept
bility gets turned on users are expected
to quit and restart any running
application and a final tip is something
off
that guy mentioned is you know sort of
be lazy about creating any data
structures associated with accessibility
so if we go back to the example of the
scroll bar with all the children you
know I would create the children when
I'm asked for them and and only keep
them around long enough to satisfy that
request and then throw them out there's
no reason to have these things around
and then they'll get out of sync if your
scroll bar changes state so it's much
simpler just to creative as needed and
now we have a couple slides talking
about the resources available to you and
the first one I want to plug is our
accessibility dev mailing list and this
is a public mailing list that you should
subscribe to you can ask all your
questions on it if you come up with some
with use of some weird widget and you
don't know how to accessorize it you
know post an email this list is trolled
by guy and myself actively and some
other engineers and we know we don't
promise that we have all the answers
accessibility has been a the whole
story's been evolving since Jaguar and
more often than we like to admit you
know people come up with weird you is
that we hadn't thought about how is this
going to work with accessibility but if
you post to this list we can usually
steer you in the right direction and
finally there's three documents relating
to accessibility one of them is for
people writing assistive apps and even
if you're just accessorizing your app it
might be useful to peruse that one and
then there's a cocoa specific document
in a carbon specific document for
accessorizing your application and that
will open it up for Q&A