Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [platform-swt-dev] How does Accessible interface works ?


Latest news...

setting breakpoint in swt.accessibility.Accessibility.get_accFocus() method,
it appear that this method is called only called 3 times.

As I understand the setFocus() method (on my WinXP):
public void setFocus(int childID) {
                checkWidget();
                COM.NotifyWinEvent (COM.EVENT_OBJECT_FOCUS, control.handle, COM.OBJID_CLIENT, childIDToOs(childID));
        }

This is the role of COM on EVENT_OBJECT_FOCUS to call back get_accFocus() ... I think.
Does it means there can be a (silent) problem during COM ... ?
(checkWidget() seems to be ok because I can see none of the potentially raised error).

Continuing to dig...

Arnaud.



Carolyn MacLeod <Carolyn_MacLeod@xxxxxxxxxx>
Sent by: platform-swt-dev-admin@xxxxxxxxxxx

06/30/2004 05:06 PM

Please respond to
platform-swt-dev

To
platform-swt-dev@xxxxxxxxxxx
cc
Subject
Re: [platform-swt-dev] How does Accessible interface works ?






You're welcome.


Think of the role as "what you want your custom widget to be like" instead of "what it looks like" or anything.

So for example, if I was implementing my little test "for real", I would probably make the red and blue squares behave very much like radio buttons, including arrows to traverse and space to select, etc.


The subset of the Windows roles that we implemented match similar roles on the GTK platform, so that's why we only have a subset. You will note that it is a large and useful/typical subset - there's only a few esoteric roles left out. But that is not to say that we wouldn't implement them if there was a really good reason to do so.


Good luck,

Carolyn



Arnaud De Muyser <ademuyser@xxxxxxxxxx>
Sent by: platform-swt-dev-admin@xxxxxxxxxxx

06/30/2004 10:33 AM

Please respond to
platform-swt-dev

To
platform-swt-dev@xxxxxxxxxxx
cc
Subject
Re: [platform-swt-dev] How does Accessible interface works ?








Thanks Carolyn for the snippet,

You know what ? I'm terribly jealous ...

because I still don't understand why yours works fine whereas mine stop to said anything after 3 times ...

I'll do deep test, kneading your code to be closer to mine, perhaps I'll learn interesting thing.


I've put one eye on ROLE listed in microsoft's web page. Why SWT choose to not implements all thing ?

this is strange be role I've tested seems to be really important for Screen reader. for example using a
Tooltip role means screen reader (at least the one I used), finish to read completly the text I return in getValue()

before starting to read another one, whereas radiobutton role you use let him stop read immediatly when a

new text is ready. Role are also really important, because screen reader said the name of role (ie: "Radio button"

for radio button role), and if we want to meet accessibility in the sense to help people who need it, why do we

confuse them reading "radio button" whereas there are no radio button ... I mean they'll think they can use space

bar to select un select as if there are really a radio button ...

Perhaps in your snippet (and in my code), the closer role we can use is ROLE_SYSTEM_DIAGRAM ...


Thanks for the example, I'll seek in it, trying to understand what happen to me.

Arnaud.


Carolyn MacLeod <Carolyn_MacLeod@xxxxxxxxxx>
Sent by: platform-swt-dev-admin@xxxxxxxxxxx

06/29/2004 11:31 PM

Please respond to
platform-swt-dev


To
platform-swt-dev@xxxxxxxxxxx
cc
Subject
Re: [platform-swt-dev] How does Accessible interface works ?










Here is a little test snippet that I had lying around. It's a Canvas with 2 colored squares on it. Each of the squares can take focus (I happened to use the tab key to traverse between them, but arrow keys is fine, too). For the role, I just randomly called them "radio buttons" because there's a "selected" one, and an "unselected" one. What kind of role do you think your widget, or its "children", should have? There are several roles on Windows that we did not implement because other platforms did not have those particular accessible roles. Here's the complete list of Windows roles, FYI. If you think one of them is important to your application, please open a bugzilla feature request against SWT and explain why you need that role.


http://msdn.microsoft.com/library/en-us/msaa/msaaccrf_4nub.asp


For some production-quality examples of custom controls that have implemented accessibile interfaces, please see CCombo, CLabel, CTabFolder, and StyledText classes in the package org.eclipse.swt.custom.


Good luck,

Carolyn


Here's the snippet:



import
org.eclipse.swt.*;
import
org.eclipse.swt.graphics.*;
import
org.eclipse.swt.widgets.*;
import
org.eclipse.swt.events.*;
import
org.eclipse.swt.accessibility.*;

public
class AccessibleShapes {
     
static Display display;
     
static Shell parentShell;
     
static Shell shell;
     
static Canvas canvas;
     
static Accessible accessible;
     
static int focusShape = -1;
     
static final Rectangle blueBounds = new Rectangle(20, 20, 100, 100);
     
static final Rectangle redBounds = new Rectangle(140, 20, 100, 100);
     
static boolean dialog = false; // true for dialog, false for plain shell
     
     
public static void main(String[] args) {
             display =
new Display();
             
if (dialog) {
                     parentShell =
new Shell(display);
                     shell =
new Shell(parentShell);
             }
else {
                     shell =
new Shell(display);
             }

             shell.setText(dialog ?
"Dialog" : "Shell");
             canvas =
new Canvas(shell, SWT.NONE);
             canvas.setSize(260, 140);

             accessible = canvas.getAccessible();


             canvas.addPaintListener(
new PaintListener() {
                     
public void paintControl(PaintEvent e) {
                             GC gc = e.gc;

                             gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE));

                             gc.fillRectangle(blueBounds);

                             
if (focusShape == 0) gc.drawFocus(blueBounds.x, blueBounds.y, blueBounds.width, blueBounds.height);

                             gc.setBackground(display.getSystemColor(SWT.COLOR_RED));

                             gc.fillRectangle(redBounds);

                             
if (focusShape == 1) gc.drawFocus(redBounds.x, redBounds.y, redBounds.width, redBounds.height);
                     }

             });

             
             canvas.addMouseListener(
new MouseAdapter() {
                     
public void mouseDown(MouseEvent e) {
                             
if (blueBounds.contains(e.x, e.y)) {
                                     setFocus(0);

                             }
else if (redBounds.contains(e.x, e.y)) {
                                     setFocus(1);

                             }
else {
                                     setFocus(-1);

                             }

                     }

             });

             
             canvas.addFocusListener(
new FocusListener() {
                     
public void focusGained(FocusEvent e) {
                             
if (focusShape == -1) {
                                     accessible.setFocus(ACC.CHILDID_SELF);

                             }
else {
                                     accessible.setFocus(focusShape);

                             }

                     }

                     
public void focusLost(FocusEvent e) {
                     }

             });

             
             canvas.addTraverseListener(
new TraverseListener() {
                     
public void keyTraversed(TraverseEvent e) {
                             
switch (e.detail) {
                                     
case SWT.TRAVERSE_TAB_NEXT:
                                     
case SWT.TRAVERSE_TAB_PREVIOUS:
                                             
if (focusShape == 0) setFocus(1);
                                             
else setFocus(0);
                                             e.doit =
true;
                                             
break;
                             }

                     }

             });


             accessible.addAccessibleListener(
new AccessibleAdapter() {
                     
public void getName(AccessibleEvent e) {
                             
switch (e.childID) {
                                     
case ACC.CHILDID_SELF: e.result = "Canvas"; break;
                                     
case 0: e.result = "Blue"; break;
                                     
case 1: e.result = "Red"; break;
                             }

                     }

             });

             accessible.addAccessibleControlListener(
new AccessibleControlAdapter() {
                     
public void getChildCount(AccessibleControlEvent e) {
                             e.detail = 2;

                     }

                     
public void getChildren(AccessibleControlEvent e) {
                             e.children =
new Integer[] {new Integer(0), new Integer(1)};
                     }

                     
public void getChildAtPoint(AccessibleControlEvent e) {
                             Point pt = canvas.toControl(e.x, e.y);

                             
if (blueBounds.contains(pt)) e.childID = 0;
                             
else if (redBounds.contains(pt)) e.childID = 1;
                             
else e.childID = ACC.CHILDID_SELF;
                     }

                     
public void getFocus(AccessibleControlEvent e) {
                             
if (canvas.isFocusControl()) {
                                     
if (focusShape == -1) e.childID = ACC.CHILDID_SELF;
                                     
else e.childID = focusShape;
                             }
else {
                                     e.childID = ACC.CHILDID_NONE;

                             }

                     }

                     
public void getLocation(AccessibleControlEvent e) {
                             
switch (e.childID) {
                                     
case ACC.CHILDID_SELF:
                                             Rectangle bounds = canvas.getBounds();

                                             e.x = bounds.x; e.y = bounds.y; e.width = bounds.width; e.height = bounds.height;

                                             
break;
                                     
case 0:
                                             e.x = blueBounds.x; e.y = blueBounds.y; e.width = blueBounds.width; e.height = blueBounds.height;

                                             
break;
                                     
case 1:
                                             e.x = redBounds.x; e.y = redBounds.y; e.width = redBounds.width; e.height = redBounds.height;

                                             
break;
                             }

                     }

                     
public void getRole(AccessibleControlEvent e) {
                             
switch (e.childID) {
                                     
case ACC.CHILDID_SELF: e.detail = ACC.ROLE_CLIENT_AREA; break;
                                     
case 0: e.detail = ACC.ROLE_RADIOBUTTON; break;
                                     
case 1: e.detail = ACC.ROLE_RADIOBUTTON; break;
                             }

                     }

                     
public void getSelection(AccessibleControlEvent e) {
                             
if (canvas.isFocusControl()) {
                                     
if (focusShape == -1) e.childID = ACC.CHILDID_SELF;
                                     
else e.childID = focusShape;
                             }
else {
                                     e.childID = ACC.CHILDID_NONE;

                             }

                     }

                     
public void getState(AccessibleControlEvent e) {
                             e.detail = ACC.STATE_FOCUSABLE;

                             
if (e.childID == ACC.CHILDID_SELF) {
                                     
if (canvas.isFocusControl() && focusShape == -1) e.detail |= ACC.STATE_FOCUSED;
                             }
else {
                                     e.detail |= ACC.STATE_SELECTABLE;

                                     
if (e.childID == focusShape) e.detail |= ACC.STATE_FOCUSED | ACC.STATE_SELECTED | ACC.STATE_CHECKED;
                             }

                     }

                     
public void getValue(AccessibleControlEvent e) {
                             
switch (e.childID) {
                                     
case ACC.CHILDID_SELF: e.result = "none"; break;
                                     
case 0: e.result = "blue"; break;
                                     
case 1: e.result = "red"; break;
                             }

                     }

             });


             shell.pack();

             shell.open();

             
if (dialog) {
                     parentShell.pack();

                     parentShell.open();

                     shell.setFocus();

                     shell = parentShell;

             }

             canvas.setFocus();

             
while (!shell.isDisposed()) {
                     
if (!display.readAndDispatch()) display.sleep();
             }

     }

     
     
static void setFocus(int newFocusShape) {
             focusShape = newFocusShape;

             canvas.redraw();

             
if (focusShape == -1) {
                     accessible.setFocus(ACC.CHILDID_SELF);

             }
else {
                     accessible.setFocus(focusShape);

             }

     }

}



Arnaud De Muyser <ademuyser@xxxxxxxxxx>
Sent by: platform-swt-dev-admin@xxxxxxxxxxx

06/29/2004 08:29 AM

Please respond to
platform-swt-dev


To
platform-swt-dev@xxxxxxxxxxx
cc
Subject
[platform-swt-dev] How does Accessible interface works ?












Hi,


I'm trying to implement accessibility on a widget I've created (from swt.Canvas).

As I can see in Eclipse 3.0 help system I implement an "org.eclipse.swt.accessibility.AccessibleControlListener" (see below),

and I do the following to setup accessible inside my widget: "getAccessible().addAccessibleControlListener( new MyAccessible() );".


My widget contains inner rectangle which are able to get the "focus" (only one can have focus at a time),

user can give the focus from a rectangle to an other using arrows keys.

To implements full accessibility, when user change the focused rectangle, I must to make the screen reader talking new data from focused rectangle,

to do this I write the following method:

private void saidFocusedEvent()

{

 this.getAccessible().setFocus( ACC.CHILDID_SELF );//doesn't work: this.handle );
}


I'm using two different screen reader:

1/ first is the Microsoft's Narrator:

    If this screen reader read all tooltips I open from my widget, it never said things when I call "saidFocusedEvent" method.


2/second is Windows Eyes 4.5 SP3:

    this one tell more things than Ms'Narrator, all tooltips, all "text" I draw in my Widget,
    But it said texts only for  the first 3 call of  "saidFocusedEvent()", after that all call to "saidFocusedEvent()" are quiet ... to bad !

    (sometimes it continue to read the first texts I've returned in MyAccessible.getValue() for each "saidFocusedEvent()" call ... to bad too ).

    (when it's quiet I can see none of the trace output I wrote in method like if interface's method are never called ...).


Does anyone have experimented this kind of behaviour ?


As I'm not the only one in development team who experiment this kind of things,

I want to know where I'm wrong in my source code ?


How can I make my accessible implementation talk data when I want to do it ?


Does anyone knows what I must return in Accessible.getRole() method ? None of the constants defined in ACC class suit me...

and if I return nothing ... screen reader just said "Custom control" without said text I return in getValue()... strange ?


Any help is really welcome, thanks a lot !


Arnaud.



PS: AccessibleControlListener implementation:


private class MyAccessible
implements AccessibleControlListener
{

public void getRole(AccessibleControlEvent e)

{

    e.detail=ACC.ROLE_TOOLTIP; //KO:_TABLECELL;//_SCROLLBAR;//_TOOLTIP; //_LABEL; //KO:_CLIENT_AREA;

System.out.println("[TITBW] Accessible["+this.hashCode()+"].getRole()");      

}  
public void getValue(AccessibleControlEvent e)
{

  e.result =getFocusedRectangleData();

System.out.println("[TIBTW] Accessible["+this.hashCode()+"].getValue() said ?=<"+s+">");      

}

public void getState(AccessibleControlEvent e)

{

  e.detail=ACC.STATE_FOCUSED ;

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getState()");      

}

public void getFocus( AccessibleControlEvent e)

{

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getFocus()");

  e.detail = ACC.CHILDID_SELF;

}

public void getChildAtPoint(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getChildAtPoint()");

}

public void getLocation(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getLocation()");

}

public void getChild(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getChild()");

}

public void getChildCount(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getChildCount()");

}

public void getDefaultAction(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getDefaultAction()");

}

public void getSelection(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getSelection()");

   e.detail = ACC.CHILDID_SELF; //ThreadInfoByTimeWidget.this.handle;

}

public void getChildren(AccessibleControlEvent e) {

System.out.println("[TITBW] Accessible["+this.hashCode()+"] getChildren()");

}

}


Back to the top