blob: cfdaa4bb094126269c796e239dec2ab1d9a41b51 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.accessibility;
import java.util.Vector;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.ole.win32.*;
import org.eclipse.swt.internal.ole.win32.*;
/**
* Instances of this class provide a bridge between application
* code and assistive technology clients. Many platforms provide
* default accessible behavior for most widgets, and this class
* allows that default behavior to be overridden. Applications
* can get the default Accessible object for a control by sending
* it <code>getAccessible</code>, and then add an accessible listener
* to override simple items like the name and help string, or they
* can add an accessible control listener to override complex items.
* As a rule of thumb, an application would only want to use the
* accessible control listener to implement accessibility for a
* custom control.
*
* @see Control#getAccessible
* @see AccessibleListener
* @see AccessibleEvent
* @see AccessibleControlListener
* @see AccessibleControlEvent
*
* @since 2.0
*/
public class Accessible {
int refCount = 0, enumIndex = 0;
COMObject objIAccessible, objIEnumVARIANT;
IAccessible iaccessible;
Vector accessibleListeners = new Vector(), accessibleControlListeners = new Vector();
Object[] variants;
Control control;
Accessible(Control control) {
this.control = control;
int[] ppvObject = new int[1];
int result = COM.CreateStdAccessibleObject(control.handle, COM.OBJID_CLIENT, COM.IIDIAccessible, ppvObject);
if (result == COM.E_NOTIMPL) return;
if (result != COM.S_OK) OLE.error(OLE.ERROR_CANNOT_CREATE_OBJECT, result);
iaccessible = new IAccessible(ppvObject[0]);
iaccessible.AddRef();
objIAccessible = new COMObject(new int[] {2,0,0,1,3,5,8,1,1,5,5,5,5,5,5,5,6,5,1,1,5,5,8,6,3,4,5,5}) {
public int method0(int[] args) {return QueryInterface(args[0], args[1]);}
public int method1(int[] args) {return AddRef();}
public int method2(int[] args) {return Release();}
// method3 GetTypeInfoCount - not implemented
// method4 GetTypeInfo - not implemented
// method5 GetIDsOfNames - not implemented
// method6 Invoke - not implemented
public int method7(int[] args) {return get_accParent(args[0]);}
public int method8(int[] args) {return get_accChildCount(args[0]);}
public int method9(int[] args) {return get_accChild(args[0], args[1], args[2], args[3], args[4]);}
public int method10(int[] args) {return get_accName(args[0], args[1], args[2], args[3], args[4]);}
public int method11(int[] args) {return get_accValue(args[0], args[1], args[2], args[3], args[4]);}
public int method12(int[] args) {return get_accDescription(args[0], args[1], args[2], args[3], args[4]);}
public int method13(int[] args) {return get_accRole(args[0], args[1], args[2], args[3], args[4]);}
public int method14(int[] args) {return get_accState(args[0], args[1], args[2], args[3], args[4]);}
public int method15(int[] args) {return get_accHelp(args[0], args[1], args[2], args[3], args[4]);}
public int method16(int[] args) {return get_accHelpTopic(args[0], args[1], args[2], args[3], args[4], args[5]);}
public int method17(int[] args) {return get_accKeyboardShortcut(args[0], args[1], args[2], args[3], args[4]);}
public int method18(int[] args) {return get_accFocus(args[0]);}
public int method19(int[] args) {return get_accSelection(args[0]);}
public int method20(int[] args) {return get_accDefaultAction(args[0], args[1], args[2], args[3], args[4]);}
public int method21(int[] args) {return accSelect(args[0], args[1], args[2], args[3], args[4]);}
public int method22(int[] args) {return accLocation(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);}
public int method23(int[] args) {return accNavigate(args[0], args[1], args[2], args[3], args[4], args[5]);}
public int method24(int[] args) {return accHitTest(args[0], args[1], args[2]);}
public int method25(int[] args) {return accDoDefaultAction(args[0], args[1], args[2], args[3]);}
public int method26(int[] args) {return put_accName(args[0], args[1], args[2], args[3], args[4]);}
public int method27(int[] args) {return put_accValue(args[0], args[1], args[2], args[3], args[4]);}
};
objIEnumVARIANT = new COMObject(new int[] {2,0,0,3,1,0,1}) {
public int method0(int[] args) {return QueryInterface(args[0], args[1]);}
public int method1(int[] args) {return AddRef();}
public int method2(int[] args) {return Release();}
public int method3(int[] args) {return Next(args[0], args[1], args[2]);}
public int method4(int[] args) {return Skip(args[0]);}
public int method5(int[] args) {return Reset();}
// method6 Clone - not implemented
};
AddRef();
}
/**
* Invokes platform specific functionality to allocate a new accessible object.
* <p>
* <b>IMPORTANT:</b> This method is <em>not</em> part of the public
* API for <code>Accessible</code>. It is marked public only so that it
* can be shared within the packages provided by SWT. It is not
* available on all platforms, and should never be called from
* application code.
* </p>
*
* @param control the control to get the accessible object for
* @return the platform specific accessible object
*
* @private
*/
public static Accessible internal_new_Accessible(Control control) {
return new Accessible(control);
}
/**
* Adds the listener to the collection of listeners who will
* be notifed when an accessible client asks for certain strings,
* such as name, description, help, or keyboard shortcut. The
* listener is notified by sending it one of the messages defined
* in the <code>AccessibleListener</code> interface.
*
* @param listener the listener that should be notified when the receiver
* is asked for a name, description, help, or keyboard shortcut string
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
* </ul>
*
* @see AccessibleListener
* @see #removeAccessibleListener
*/
public void addAccessibleListener(AccessibleListener listener) {
checkWidget();
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
accessibleListeners.addElement(listener);
}
/**
* Removes the listener from the collection of listeners who will
* be notifed when an accessible client asks for certain strings,
* such as name, description, help, or keyboard shortcut.
*
* @param listener the listener that should no longer be notified when the receiver
* is asked for a name, description, help, or keyboard shortcut string
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
* </ul>
*
* @see AccessibleListener
* @see #addDisposeListener
*/
public void removeAccessibleListener(AccessibleListener listener) {
checkWidget();
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
accessibleListeners.removeElement(listener);
}
/**
* Adds the listener to the collection of listeners who will
* be notifed when an accessible client asks for custom control
* specific information. The listener is notified by sending it
* one of the messages defined in the <code>AccessibleControlListener</code>
* interface.
*
* @param listener the listener that should be notified when the receiver
* is asked for custom control specific information
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
* </ul>
*
* @see AccessibleControlListener
* @see #removeAccessibleControlListener
*/
public void addAccessibleControlListener(AccessibleControlListener listener) {
checkWidget();
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
accessibleControlListeners.addElement(listener);
}
/**
* Removes the listener from the collection of listeners who will
* be notifed when an accessible client asks for custom control
* specific information.
*
* @param listener the listener that should no longer be notified when the receiver
* is asked for custom control specific information
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
* </ul>
*
* @see AccessibleControlListener
* @see #addAccessibleControlListener
*/
public void removeAccessibleControlListener(AccessibleControlListener listener) {
checkWidget();
if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
accessibleControlListeners.removeElement(listener);
}
/**
* Sends a message to accessible clients indicating that the focus
* has changed within a custom control.
*
* @param childID an identifier specifying a child of the control
*
* @exception SWTException <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver's control has been disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver's control</li>
* </ul>
*/
public void setFocus(int childID) {
checkWidget();
int id;
if (childID == ACC.CHILDID_SELF) id = COM.CHILDID_SELF;
else if (control instanceof Tree) id = childID; // Tree item childIDs are pointers
else id = childID + 1; // All other childIDs are 1-based indices
COM.NotifyWinEvent (COM.EVENT_OBJECT_FOCUS, control.handle, COM.OBJID_CLIENT, id);
}
/**
* Invokes platform specific functionality to dispose an accessible object.
* <p>
* <b>IMPORTANT:</b> This method is <em>not</em> part of the public
* API for <code>Accessible</code>. It is marked public only so that it
* can be shared within the packages provided by SWT. It is not
* available on all platforms, and should never be called from
* application code.
* </p>
*
* @private
*/
public void internal_dispose_Accessible() {
if (iaccessible != null)
iaccessible.Release();
iaccessible = null;
Release();
}
/**
* Invokes platform specific functionality to handle a window message.
* <p>
* <b>IMPORTANT:</b> This method is <em>not</em> part of the public
* API for <code>Accessible</code>. It is marked public only so that it
* can be shared within the packages provided by SWT. It is not
* available on all platforms, and should never be called from
* application code.
* </p>
*
* @private
*/
public int internal_WM_GETOBJECT (int wParam, int lParam) {
if (objIAccessible == null) return 0;
if (lParam == COM.OBJID_CLIENT) {
return COM.LresultFromObject(COM.IIDIAccessible, wParam, objIAccessible.getAddress());
}
return 0;
}
int QueryInterface(int arg1, int arg2) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
GUID guid = new GUID();
COM.MoveMemory(guid, arg1, GUID.sizeof);
if (COM.IsEqualGUID(guid, COM.IIDIUnknown)) {
COM.MoveMemory(arg2, new int[] { objIAccessible.getAddress()}, 4);
AddRef();
return COM.S_OK;
}
if (COM.IsEqualGUID(guid, COM.IIDIDispatch)) {
COM.MoveMemory(arg2, new int[] { objIAccessible.getAddress()}, 4);
AddRef();
return COM.S_OK;
}
if (COM.IsEqualGUID(guid, COM.IIDIAccessible)) {
COM.MoveMemory(arg2, new int[] { objIAccessible.getAddress()}, 4);
AddRef();
return COM.S_OK;
}
if (COM.IsEqualGUID(guid, COM.IIDIEnumVARIANT)) {
COM.MoveMemory(arg2, new int[] { objIEnumVARIANT.getAddress()}, 4);
AddRef();
enumIndex = 0;
return COM.S_OK;
}
int[] ppvObject = new int[1];
int result = iaccessible.QueryInterface(guid, ppvObject);
COM.MoveMemory(arg2, ppvObject, 4);
return result;
}
int AddRef() {
refCount++;
return refCount;
}
int Release() {
refCount--;
if (refCount == 0) {
if (objIAccessible != null)
objIAccessible.dispose();
objIAccessible = null;
if (objIEnumVARIANT != null)
objIEnumVARIANT.dispose();
objIEnumVARIANT = null;
}
return refCount;
}
int accDoDefaultAction(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
// Currently, we don't let the application override this. Forward to the proxy.
int code = iaccessible.accDoDefaultAction(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
return code;
}
int accHitTest(int xLeft, int yTop, int pvarChild) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if (accessibleControlListeners.size() == 0) {
return iaccessible.accHitTest(xLeft, yTop, pvarChild);
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
event.childID = ACC.CHILDID_NONE;
event.x = xLeft;
event.y = yTop;
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getChildAtPoint(event);
}
int childID = event.childID;
if (childID == ACC.CHILDID_NONE) {
return iaccessible.accHitTest(xLeft, yTop, pvarChild);
}
if (childID == ACC.CHILDID_SELF) childID = COM.CHILDID_SELF;
else if (!(control instanceof Tree)) childID++; // Tree item childIDs are pointers (not 1-based indices)
COM.MoveMemory(pvarChild, new short[] { COM.VT_I4 }, 2);
COM.MoveMemory(pvarChild + 8, new int[] { childID }, 4);
return COM.S_OK;
}
int accLocation(int pxLeft, int pyTop, int pcxWidth, int pcyHeight, int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default location from the OS. */
int osLeft = 0, osTop = 0, osWidth = 0, osHeight = 0;
int code = iaccessible.accLocation(pxLeft, pyTop, pcxWidth, pcyHeight, varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
if (accessibleControlListeners.size() == 0) return code;
if (code == COM.S_OK) {
int[] pLeft = new int[1], pTop = new int[1], pWidth = new int[1], pHeight = new int[1];
COM.MoveMemory(pLeft, pxLeft, 4);
COM.MoveMemory(pTop, pyTop, 4);
COM.MoveMemory(pWidth, pcxWidth, 4);
COM.MoveMemory(pHeight, pcyHeight, 4);
osLeft = pLeft[0]; osTop = pTop[0]; osWidth = pWidth[0]; osHeight = pHeight[0];
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
if (varChild_lVal == COM.CHILDID_SELF) event.childID = ACC.CHILDID_SELF;
else if (control instanceof Tree) event.childID = varChild_lVal; // Tree item childIDs are pointers
else event.childID = varChild_lVal - 1; // All other childIDs are 1-based indices
event.x = osLeft;
event.y = osTop;
event.width = osWidth;
event.height = osHeight;
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getLocation(event);
}
OS.MoveMemory(pxLeft, new int[] { event.x }, 4);
OS.MoveMemory(pyTop, new int[] { event.y }, 4);
OS.MoveMemory(pcxWidth, new int[] { event.width }, 4);
OS.MoveMemory(pcyHeight, new int[] { event.height }, 4);
return COM.S_OK;
}
int accNavigate(int navDir, int varStart_vt, int varStart_reserved1, int varStart_lVal, int varStart_reserved2, int pvarEndUpAt) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
// Currently, we don't let the application override this. Forward to the proxy.
int code = iaccessible.accNavigate(navDir, varStart_vt, varStart_reserved1, varStart_lVal, varStart_reserved2, pvarEndUpAt);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
return code;
}
int accSelect(int flagsSelect, int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
// Currently, we don't let the application override this. Forward to the proxy.
int code = iaccessible.accSelect(flagsSelect, varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
return code;
}
int get_accChild(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int ppdispChild) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
if (accessibleControlListeners.size() == 0) {
int code = iaccessible.get_accChild(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, ppdispChild);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
return code;
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
if (varChild_lVal == COM.CHILDID_SELF) event.childID = ACC.CHILDID_SELF;
else if (control instanceof Tree) event.childID = varChild_lVal; // Tree item childIDs are pointers
else event.childID = varChild_lVal - 1; // All other childIDs are 1-based indices
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getChild(event);
}
Accessible accessible = event.accessible;
if (accessible != null) {
COM.MoveMemory(ppdispChild, new int[] { accessible.objIAccessible.getAddress() }, 4);
return COM.S_OK;
}
return COM.S_FALSE;
}
int get_accChildCount(int pcountChildren) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
/* Get the default child count from the OS. */
int osChildCount = 0;
int code = iaccessible.get_accChildCount(pcountChildren);
if (accessibleControlListeners.size() == 0) return code;
if (code == COM.S_OK) {
int[] pChildCount = new int[1];
COM.MoveMemory(pChildCount, pcountChildren, 4);
osChildCount = pChildCount[0];
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
event.childID = ACC.CHILDID_SELF;
event.detail = osChildCount;
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getChildCount(event);
}
COM.MoveMemory(pcountChildren, new int[] { event.detail }, 4);
return COM.S_OK;
}
int get_accDefaultAction(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pszDefaultAction) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default defaultAction from the OS. */
String osDefaultAction = null;
int code = iaccessible.get_accDefaultAction(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pszDefaultAction);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
if (accessibleControlListeners.size() == 0) return code;
if (code == COM.S_OK) {
int[] pDefaultAction = new int[1];
COM.MoveMemory(pDefaultAction, pszDefaultAction, 4);
int size = COM.SysStringByteLen(pDefaultAction[0]);
if (size > 0) {
char[] buffer = new char[(size + 1) /2];
COM.MoveMemory(buffer, pDefaultAction[0], size);
osDefaultAction = new String(buffer);
}
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
if (varChild_lVal == COM.CHILDID_SELF) event.childID = ACC.CHILDID_SELF;
else if (control instanceof Tree) event.childID = varChild_lVal; // Tree item childIDs are pointers
else event.childID = varChild_lVal - 1; // All other childIDs are 1-based indices
event.result = osDefaultAction;
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getDefaultAction(event);
}
if (event.result == null) return code;
char[] data = (event.result + "\0").toCharArray();
int ptr = COM.SysAllocString(data);
COM.MoveMemory(pszDefaultAction, new int[] { ptr }, 4);
return COM.S_OK;
}
int get_accDescription(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pszDescription) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default description from the OS. */
String osDescription = null;
int code = iaccessible.get_accDescription(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pszDescription);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
if (accessibleListeners.size() == 0) return code;
if (code == COM.S_OK) {
int[] pDescription = new int[1];
COM.MoveMemory(pDescription, pszDescription, 4);
int size = COM.SysStringByteLen(pDescription[0]);
if (size > 0) {
char[] buffer = new char[(size + 1) /2];
COM.MoveMemory(buffer, pDescription[0], size);
osDescription = new String(buffer);
}
}
AccessibleEvent event = new AccessibleEvent(this);
if (varChild_lVal == COM.CHILDID_SELF) event.childID = ACC.CHILDID_SELF;
else if (control instanceof Tree) event.childID = varChild_lVal; // Tree item childIDs are pointers
else event.childID = varChild_lVal - 1; // All other childIDs are 1-based indices
event.result = osDescription;
for (int i = 0; i < accessibleListeners.size(); i++) {
AccessibleListener listener = (AccessibleListener) accessibleListeners.elementAt(i);
listener.getDescription(event);
}
if (event.result == null) return code;
char[] data = (event.result + "\0").toCharArray();
int ptr = COM.SysAllocString(data);
COM.MoveMemory(pszDescription, new int[] { ptr }, 4);
return COM.S_OK;
}
int get_accFocus(int pvarChild) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
/* Get the default focus child from the OS. */
int osChild = ACC.CHILDID_NONE;
int code = iaccessible.get_accFocus(pvarChild);
if (accessibleControlListeners.size() == 0) return code;
if (code == COM.S_OK) {
short[] pvt = new short[1];
COM.MoveMemory(pvt, pvarChild, 2);
if (pvt[0] == COM.VT_I4) {
int[] pChild = new int[1];
COM.MoveMemory(pChild, pvarChild + 8, 4);
osChild = (pChild[0] == COM.CHILDID_SELF) ? ACC.CHILDID_SELF : pChild[0] - 1;
}
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
event.childID = osChild;
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getFocus(event);
}
Accessible accessible = event.accessible;
if (accessible != null) {
COM.MoveMemory(pvarChild, new short[] { COM.VT_DISPATCH }, 2);
COM.MoveMemory(pvarChild + 8, new int[] { accessible.objIAccessible.getAddress() }, 4);
return COM.S_OK;
}
int childID = event.childID;
if (childID == ACC.CHILDID_NONE) {
COM.MoveMemory(pvarChild, new short[] { COM.VT_EMPTY }, 2);
return COM.S_FALSE;
}
if (childID == ACC.CHILDID_SELF) {
COM.MoveMemory(pvarChild, new short[] { COM.VT_DISPATCH }, 2);
COM.MoveMemory(pvarChild + 8, new int[] { objIAccessible.getAddress() }, 4);
return COM.S_OK;
}
COM.MoveMemory(pvarChild, new short[] { COM.VT_I4 }, 2);
COM.MoveMemory(pvarChild + 8, new int[] { childID + 1 }, 4);
return COM.S_OK;
}
int get_accHelp(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pszHelp) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default help string from the OS. */
String osHelp = null;
int code = iaccessible.get_accHelp(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pszHelp);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
if (accessibleListeners.size() == 0) return code;
if (code == COM.S_OK) {
int[] pHelp = new int[1];
COM.MoveMemory(pHelp, pszHelp, 4);
int size = COM.SysStringByteLen(pHelp[0]);
if (size > 0) {
char[] buffer = new char[(size + 1) /2];
COM.MoveMemory(buffer, pHelp[0], size);
osHelp = new String(buffer);
}
}
AccessibleEvent event = new AccessibleEvent(this);
if (varChild_lVal == COM.CHILDID_SELF) event.childID = ACC.CHILDID_SELF;
else if (control instanceof Tree) event.childID = varChild_lVal; // Tree item childIDs are pointers
else event.childID = varChild_lVal - 1; // All other childIDs are 1-based indices
event.result = osHelp;
for (int i = 0; i < accessibleListeners.size(); i++) {
AccessibleListener listener = (AccessibleListener) accessibleListeners.elementAt(i);
listener.getHelp(event);
}
if (event.result == null) return code;
char[] data = (event.result + "\0").toCharArray();
int ptr = COM.SysAllocString(data);
COM.MoveMemory(pszHelp, new int[] { ptr }, 4);
return COM.S_OK;
}
int get_accHelpTopic(int pszHelpFile, int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pidTopic) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
// Currently, we don't let the application override this. Forward to the proxy.
int code = iaccessible.get_accHelpTopic(pszHelpFile, varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pidTopic);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
return code;
}
int get_accKeyboardShortcut(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pszKeyboardShortcut) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default keyboard shortcut from the OS. */
String osKeyboardShortcut = null;
int code = iaccessible.get_accKeyboardShortcut(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pszKeyboardShortcut);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
if (accessibleListeners.size() == 0) return code;
if (code == COM.S_OK) {
int[] pKeyboardShortcut = new int[1];
COM.MoveMemory(pKeyboardShortcut, pszKeyboardShortcut, 4);
int size = COM.SysStringByteLen(pKeyboardShortcut[0]);
if (size > 0) {
char[] buffer = new char[(size + 1) /2];
COM.MoveMemory(buffer, pKeyboardShortcut[0], size);
osKeyboardShortcut = new String(buffer);
}
}
AccessibleEvent event = new AccessibleEvent(this);
if (varChild_lVal == COM.CHILDID_SELF) event.childID = ACC.CHILDID_SELF;
else if (control instanceof Tree) event.childID = varChild_lVal; // Tree item childIDs are pointers
else event.childID = varChild_lVal - 1; // All other childIDs are 1-based indices
event.result = osKeyboardShortcut;
for (int i = 0; i < accessibleListeners.size(); i++) {
AccessibleListener listener = (AccessibleListener) accessibleListeners.elementAt(i);
listener.getKeyboardShortcut(event);
}
if (event.result == null) return code;
char[] data = (event.result + "\0").toCharArray();
int ptr = COM.SysAllocString(data);
COM.MoveMemory(pszKeyboardShortcut, new int[] { ptr }, 4);
return COM.S_OK;
}
int get_accName(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pszName) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default name from the OS. */
String osName = null;
int code = iaccessible.get_accName(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pszName);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
if (accessibleListeners.size() == 0) return code;
if (code == COM.S_OK) {
int[] pName = new int[1];
COM.MoveMemory(pName, pszName, 4);
int size = COM.SysStringByteLen(pName[0]);
if (size > 0) {
char[] buffer = new char[(size + 1) /2];
COM.MoveMemory(buffer, pName[0], size);
osName = new String(buffer);
}
}
AccessibleEvent event = new AccessibleEvent(this);
if (varChild_lVal == COM.CHILDID_SELF) event.childID = ACC.CHILDID_SELF;
else if (control instanceof Tree) event.childID = varChild_lVal; // Tree item childIDs are pointers
else event.childID = varChild_lVal - 1; // All other childIDs are 1-based indices
event.result = osName;
for (int i = 0; i < accessibleListeners.size(); i++) {
AccessibleListener listener = (AccessibleListener) accessibleListeners.elementAt(i);
listener.getName(event);
}
if (event.result == null) return code;
char[] data = (event.result + "\0").toCharArray();
int ptr = COM.SysAllocString(data);
COM.MoveMemory(pszName, new int[] { ptr }, 4);
return COM.S_OK;
}
int get_accParent(int ppdispParent) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
// Currently, we don't let the application override this. Forward to the proxy.
return iaccessible.get_accParent(ppdispParent);
}
int get_accRole(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pvarRole) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default role from the OS. */
int osRole = COM.ROLE_SYSTEM_CLIENT;
int code = iaccessible.get_accRole(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pvarRole);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
// TEMPORARY CODE - process tree and table even if there are no apps listening
if (accessibleControlListeners.size() == 0 && !(control instanceof Tree || control instanceof Table)) return code;
if (code == COM.S_OK) {
short[] pvt = new short[1];
COM.MoveMemory(pvt, pvarRole, 2);
if (pvt[0] == COM.VT_I4) {
int[] pRole = new int[1];
COM.MoveMemory(pRole, pvarRole + 8, 4);
osRole = pRole[0];
}
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
event.detail = osToRole(osRole);
if (varChild_lVal == COM.CHILDID_SELF) {
event.childID = ACC.CHILDID_SELF;
} else {
if (control instanceof Tree) {
/* Tree item childIDs are pointers (not 1-based indices). */
event.childID = varChild_lVal;
// TEMPORARY CODE
/* Currently our checkbox tree is emulated using state mask images,
* so we need to specify 'checkbox' role for the items here. */
if ((control.getStyle() & SWT.CHECK) != 0) event.detail = ACC.ROLE_CHECKBUTTON;
} else if (control instanceof Table) {
event.childID = varChild_lVal - 1;
// TEMPORARY CODE
/* Currently our checkbox table is emulated using state mask images,
* so we need to specify 'checkbox' role for the items here. */
if ((control.getStyle() & SWT.CHECK) != 0) event.detail = ACC.ROLE_CHECKBUTTON;
} else {
event.childID = varChild_lVal - 1;
}
}
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getRole(event);
}
int role = roleToOs(event.detail);
COM.MoveMemory(pvarRole, new short[] { COM.VT_I4 }, 2);
COM.MoveMemory(pvarRole + 8, new int[] { role }, 4);
return COM.S_OK;
}
int get_accSelection(int pvarChildren) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
/* Get the default selection from the OS. */
int osChild = ACC.CHILDID_NONE;
int code = iaccessible.get_accSelection(pvarChildren);
if (accessibleControlListeners.size() == 0) return code;
if (code == COM.S_OK) {
short[] pvt = new short[1];
COM.MoveMemory(pvt, pvarChildren, 2);
if (pvt[0] == COM.VT_I4) {
int[] pChild = new int[1];
COM.MoveMemory(pChild, pvarChildren + 8, 4);
osChild = (pChild[0] == COM.CHILDID_SELF) ? ACC.CHILDID_SELF : pChild[0] - 1;
} else if (pvt[0] == COM.VT_UNKNOWN) {
osChild = ACC.CHILDID_MULTIPLE;
/* Should get IEnumVARIANT from punkVal field... need better API here... */
}
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
event.childID = osChild;
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getSelection(event);
}
Accessible accessible = event.accessible;
if (accessible != null) {
COM.MoveMemory(pvarChildren, new short[] { COM.VT_DISPATCH }, 2);
COM.MoveMemory(pvarChildren + 8, new int[] { accessible.objIAccessible.getAddress() }, 4);
return COM.S_OK;
}
int childID = event.childID;
if (childID == ACC.CHILDID_NONE) {
COM.MoveMemory(pvarChildren, new short[] { COM.VT_EMPTY }, 2);
return COM.S_FALSE;
}
if (childID == ACC.CHILDID_MULTIPLE) {
COM.MoveMemory(pvarChildren, new short[] { COM.VT_UNKNOWN }, 2);
/* Should return an IEnumVARIANT for this... so the next line is wrong... need better API here... */
COM.MoveMemory(pvarChildren + 8, new int[] { objIAccessible.getAddress() }, 4);
return COM.S_OK;
}
if (childID == ACC.CHILDID_SELF) {
COM.MoveMemory(pvarChildren, new short[] { COM.VT_DISPATCH }, 2);
COM.MoveMemory(pvarChildren + 8, new int[] { objIAccessible.getAddress() }, 4);
return COM.S_OK;
}
COM.MoveMemory(pvarChildren, new short[] { COM.VT_I4 }, 2);
COM.MoveMemory(pvarChildren + 8, new int[] { childID + 1 }, 4);
return COM.S_OK;
}
int get_accState(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pvarState) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default state from the OS. */
int osState = 0;
int code = iaccessible.get_accState(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pvarState);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
// TEMPORARY CODE - process tree and table even if there are no apps listening
if (accessibleControlListeners.size() == 0 && !(control instanceof Tree || control instanceof Table)) return code;
if (code == COM.S_OK) {
short[] pvt = new short[1];
COM.MoveMemory(pvt, pvarState, 2);
if (pvt[0] == COM.VT_I4) {
int[] pState = new int[1];
COM.MoveMemory(pState, pvarState + 8, 4);
osState = pState[0];
}
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
event.detail = osToState(osState);
if (varChild_lVal == COM.CHILDID_SELF) {
event.childID = ACC.CHILDID_SELF;
} else {
if (control instanceof Tree) {
/* Tree item childIDs are pointers (not 1-based indices). */
event.childID = varChild_lVal;
// TEMPORARY CODE
/* Currently our checkbox tree is emulated using state mask images,
* so we need to determine if the item is 'checked' here. */
int hwnd = control.handle;
TVITEM tvItem = new TVITEM ();
tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
tvItem.hItem = varChild_lVal;
tvItem.stateMask = OS.TVIS_STATEIMAGEMASK;
int result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, tvItem);
boolean checked = (result != 0) && (((tvItem.state >> 12) & 1) == 0);
if (checked) event.detail |= ACC.STATE_CHECKED;
} else if (control instanceof Table) {
event.childID = varChild_lVal - 1;
// TEMPORARY CODE
/* Currently our checkbox table is emulated using state mask images,
* so we need to determine if the item is 'checked' here. */
Table table = (Table) control;
TableItem item = table.getItem(event.childID);
if (item != null) {
if (item.getChecked()) event.detail |= ACC.STATE_CHECKED;
}
} else {
event.childID = varChild_lVal - 1;
}
}
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getState(event);
}
int state = stateToOs(event.detail);
COM.MoveMemory(pvarState, new short[] { COM.VT_I4 }, 2);
COM.MoveMemory(pvarState + 8, new int[] { state }, 4);
return COM.S_OK;
}
int get_accValue(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int pszValue) {
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
if ((varChild_vt & 0xFFFF) != COM.VT_I4) return COM.E_INVALIDARG;
/* Get the default value string from the OS. */
String osValue = null;
int code = iaccessible.get_accValue(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, pszValue);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
if (accessibleControlListeners.size() == 0) return code;
if (code == COM.S_OK) {
int[] pValue = new int[1];
COM.MoveMemory(pValue, pszValue, 4);
int size = COM.SysStringByteLen(pValue[0]);
if (size > 0) {
char[] buffer = new char[(size + 1) /2];
COM.MoveMemory(buffer, pValue[0], size);
osValue = new String(buffer);
}
}
AccessibleControlEvent event = new AccessibleControlEvent(this);
if (varChild_lVal == COM.CHILDID_SELF) event.childID = ACC.CHILDID_SELF;
else if (control instanceof Tree) event.childID = varChild_lVal; // Tree item childIDs are pointers
else event.childID = varChild_lVal - 1; // All other childIDs are 1-based indices
event.result = osValue;
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getValue(event);
}
if (event.result == null) return code;
char[] data = (event.result + "\0").toCharArray();
int ptr = COM.SysAllocString(data);
COM.MoveMemory(pszValue, new int[] { ptr }, 4);
return COM.S_OK;
}
int put_accName(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int szName) {
// MSAA: this method is no longer supported
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
// We don't implement this. Forward to the proxy.
int code = iaccessible.put_accName(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, szName);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
return code;
}
int put_accValue(int varChild_vt, int varChild_reserved1, int varChild_lVal, int varChild_reserved2, int szValue) {
// MSAA: this method is typically only used for edit controls
if (iaccessible == null) return COM.CO_E_OBJNOTCONNECTED;
// We don't implement this. Forward to the proxy.
int code = iaccessible.put_accValue(varChild_vt, varChild_reserved1, varChild_lVal, varChild_reserved2, szValue);
if (code == COM.E_INVALIDARG) code = COM.S_FALSE; // proxy doesn't know about app childID
return code;
}
/* IEnumVARIANT methods: Next, Skip, Reset */
/* Retrieve the next celt items in the enumeration sequence.
* If there are fewer than the requested number of elements left
* in the sequence, retrieve the remaining elements.
* The number of elements actually retrieved is returned in pceltFetched
* (unless the caller passed in NULL for that parameter).
*/
int Next(int celt, int rgvar, int pceltFetched) {
/* If there are no listeners, query the proxy for
* its IEnumVariant, and get the Next items from it.
*/
if (accessibleControlListeners.size() == 0) {
int[] ppvObject = new int[1];
int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
if (code != COM.S_OK) return code;
IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
int[] celtFetched = new int[1];
code = ienumvariant.Next(celt, rgvar, celtFetched);
COM.MoveMemory(pceltFetched, celtFetched, 4);
return code;
}
if (rgvar == 0) return COM.E_INVALIDARG;
if (pceltFetched == 0 && celt != 1) return COM.E_INVALIDARG;
if (enumIndex == 0) {
AccessibleControlEvent event = new AccessibleControlEvent(this);
event.childID = ACC.CHILDID_SELF;
for (int i = 0; i < accessibleControlListeners.size(); i++) {
AccessibleControlListener listener = (AccessibleControlListener) accessibleControlListeners.elementAt(i);
listener.getChildren(event);
}
variants = event.children;
}
Object[] nextItems = null;
if (variants != null && celt >= 1) {
int endIndex = enumIndex + celt - 1;
if (endIndex > (variants.length - 1)) endIndex = variants.length - 1;
if (enumIndex <= endIndex) {
nextItems = new Object[endIndex - enumIndex + 1];
for (int i = 0; i < nextItems.length; i++) {
Object child = variants[enumIndex];
if (child instanceof Integer) {
nextItems[i] = new Integer(((Integer)child).intValue() + 1);
} else {
nextItems[i] = child;
}
enumIndex++;
}
}
}
if (nextItems != null) {
for (int i = 0; i < nextItems.length; i++) {
Object nextItem = nextItems[i];
if (nextItem instanceof Integer) {
int item = ((Integer) nextItem).intValue();
COM.MoveMemory(rgvar + i * 16, new short[] { COM.VT_I4 }, 2);
COM.MoveMemory(rgvar + i * 16 + 8, new int[] { item }, 4);
} else {
int address = ((Accessible) nextItem).objIAccessible.getAddress();
COM.MoveMemory(rgvar + i * 16, new short[] { COM.VT_DISPATCH }, 2);
COM.MoveMemory(rgvar + i * 16 + 8, new int[] { address }, 4);
}
}
if (pceltFetched != 0)
COM.MoveMemory(pceltFetched, new int[] {nextItems.length}, 4);
if (nextItems.length == celt) return COM.S_OK;
} else {
if (pceltFetched != 0)
COM.MoveMemory(pceltFetched, new int[] {0}, 4);
}
return COM.S_FALSE;
}
/* Skip over the specified number of elements in the enumeration sequence. */
int Skip(int celt) {
/* If there are no listeners, query the proxy
* for its IEnumVariant, and tell it to Skip.
*/
if (accessibleControlListeners.size() == 0) {
int[] ppvObject = new int[1];
int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
if (code != COM.S_OK) return code;
IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
code = ienumvariant.Skip(celt);
return code;
}
if (celt < 1 ) return COM.E_INVALIDARG;
enumIndex += celt;
if (enumIndex > (variants.length - 1)) {
enumIndex = variants.length - 1;
return COM.S_FALSE;
}
return COM.S_OK;
}
/* Reset the enumeration sequence to the beginning. */
int Reset() {
/* If there are no listeners, query the proxy
* for its IEnumVariant, and tell it to Reset.
*/
if (accessibleControlListeners.size() == 0) {
int[] ppvObject = new int[1];
int code = iaccessible.QueryInterface(COM.IIDIEnumVARIANT, ppvObject);
if (code != COM.S_OK) return code;
IEnumVARIANT ienumvariant = new IEnumVARIANT(ppvObject[0]);
code = ienumvariant.Reset();
return code;
}
enumIndex = 0;
return COM.S_OK;
}
int stateToOs(int state) {
int osState = 0;
if ((state & ACC.STATE_SELECTED) != 0) osState |= COM.STATE_SYSTEM_SELECTED;
if ((state & ACC.STATE_SELECTABLE) != 0) osState |= COM.STATE_SYSTEM_SELECTABLE;
if ((state & ACC.STATE_MULTISELECTABLE) != 0) osState |= COM.STATE_SYSTEM_MULTISELECTABLE;
if ((state & ACC.STATE_FOCUSED) != 0) osState |= COM.STATE_SYSTEM_FOCUSED;
if ((state & ACC.STATE_FOCUSABLE) != 0) osState |= COM.STATE_SYSTEM_FOCUSABLE;
if ((state & ACC.STATE_PRESSED) != 0) osState |= COM.STATE_SYSTEM_PRESSED;
if ((state & ACC.STATE_CHECKED) != 0) osState |= COM.STATE_SYSTEM_CHECKED;
if ((state & ACC.STATE_EXPANDED) != 0) osState |= COM.STATE_SYSTEM_EXPANDED;
if ((state & ACC.STATE_COLLAPSED) != 0) osState |= COM.STATE_SYSTEM_COLLAPSED;
if ((state & ACC.STATE_HOTTRACKED) != 0) osState |= COM.STATE_SYSTEM_HOTTRACKED;
if ((state & ACC.STATE_BUSY) != 0) osState |= COM.STATE_SYSTEM_BUSY;
if ((state & ACC.STATE_READONLY) != 0) osState |= COM.STATE_SYSTEM_READONLY;
if ((state & ACC.STATE_INVISIBLE) != 0) osState |= COM.STATE_SYSTEM_INVISIBLE;
if ((state & ACC.STATE_OFFSCREEN) != 0) osState |= COM.STATE_SYSTEM_OFFSCREEN;
if ((state & ACC.STATE_SIZEABLE) != 0) osState |= COM.STATE_SYSTEM_SIZEABLE;
return osState;
}
int osToState(int osState) {
int state = ACC.STATE_NORMAL;
if ((osState & COM.STATE_SYSTEM_SELECTED) != 0) state |= ACC.STATE_SELECTED;
if ((osState & COM.STATE_SYSTEM_SELECTABLE) != 0) state |= ACC.STATE_SELECTABLE;
if ((osState & COM.STATE_SYSTEM_MULTISELECTABLE) != 0) state |= ACC.STATE_MULTISELECTABLE;
if ((osState & COM.STATE_SYSTEM_FOCUSED) != 0) state |= ACC.STATE_FOCUSED;
if ((osState & COM.STATE_SYSTEM_FOCUSABLE) != 0) state |= ACC.STATE_FOCUSABLE;
if ((osState & COM.STATE_SYSTEM_PRESSED) != 0) state |= ACC.STATE_PRESSED;
if ((osState & COM.STATE_SYSTEM_CHECKED) != 0) state |= ACC.STATE_CHECKED;
if ((osState & COM.STATE_SYSTEM_EXPANDED) != 0) state |= ACC.STATE_EXPANDED;
if ((osState & COM.STATE_SYSTEM_COLLAPSED) != 0) state |= ACC.STATE_COLLAPSED;
if ((osState & COM.STATE_SYSTEM_HOTTRACKED) != 0) state |= ACC.STATE_HOTTRACKED;
if ((osState & COM.STATE_SYSTEM_BUSY) != 0) state |= ACC.STATE_BUSY;
if ((osState & COM.STATE_SYSTEM_READONLY) != 0) state |= ACC.STATE_READONLY;
if ((osState & COM.STATE_SYSTEM_INVISIBLE) != 0) state |= ACC.STATE_INVISIBLE;
if ((osState & COM.STATE_SYSTEM_OFFSCREEN) != 0) state |= ACC.STATE_OFFSCREEN;
if ((osState & COM.STATE_SYSTEM_SIZEABLE) != 0) state |= ACC.STATE_SIZEABLE;
return state;
}
int roleToOs(int role) {
switch (role) {
case ACC.ROLE_CLIENT_AREA: return COM.ROLE_SYSTEM_CLIENT;
case ACC.ROLE_WINDOW: return COM.ROLE_SYSTEM_WINDOW;
case ACC.ROLE_MENUBAR: return COM.ROLE_SYSTEM_MENUBAR;
case ACC.ROLE_MENU: return COM.ROLE_SYSTEM_MENUPOPUP;
case ACC.ROLE_MENUITEM: return COM.ROLE_SYSTEM_MENUITEM;
case ACC.ROLE_SEPARATOR: return COM.ROLE_SYSTEM_SEPARATOR;
case ACC.ROLE_TOOLTIP: return COM.ROLE_SYSTEM_TOOLTIP;
case ACC.ROLE_SCROLLBAR: return COM.ROLE_SYSTEM_SCROLLBAR;
case ACC.ROLE_DIALOG: return COM.ROLE_SYSTEM_DIALOG;
case ACC.ROLE_LABEL: return COM.ROLE_SYSTEM_STATICTEXT;
case ACC.ROLE_PUSHBUTTON: return COM.ROLE_SYSTEM_PUSHBUTTON;
case ACC.ROLE_CHECKBUTTON: return COM.ROLE_SYSTEM_CHECKBUTTON;
case ACC.ROLE_RADIOBUTTON: return COM.ROLE_SYSTEM_RADIOBUTTON;
case ACC.ROLE_COMBOBOX: return COM.ROLE_SYSTEM_COMBOBOX;
case ACC.ROLE_TEXT: return COM.ROLE_SYSTEM_TEXT;
case ACC.ROLE_TOOLBAR: return COM.ROLE_SYSTEM_TOOLBAR;
case ACC.ROLE_LIST: return COM.ROLE_SYSTEM_LIST;
case ACC.ROLE_LISTITEM: return COM.ROLE_SYSTEM_LISTITEM;
case ACC.ROLE_TABLE: return COM.ROLE_SYSTEM_TABLE;
case ACC.ROLE_TABLECOLUMN: return COM.ROLE_SYSTEM_COLUMNHEADER;
case ACC.ROLE_TREE: return COM.ROLE_SYSTEM_OUTLINE;
case ACC.ROLE_TABFOLDER: return COM.ROLE_SYSTEM_PAGETABLIST;
case ACC.ROLE_TABITEM: return COM.ROLE_SYSTEM_PAGETAB;
case ACC.ROLE_PROGRESSBAR: return COM.ROLE_SYSTEM_PROGRESSBAR;
case ACC.ROLE_SLIDER: return COM.ROLE_SYSTEM_SLIDER;
}
return COM.ROLE_SYSTEM_CLIENT;
}
int osToRole(int osRole) {
int role = COM.ROLE_SYSTEM_CLIENT;
switch (osRole) {
case COM.ROLE_SYSTEM_CLIENT: return ACC.ROLE_CLIENT_AREA;
case COM.ROLE_SYSTEM_WINDOW: return ACC.ROLE_WINDOW;
case COM.ROLE_SYSTEM_MENUBAR: return ACC.ROLE_MENUBAR;
case COM.ROLE_SYSTEM_MENUPOPUP: return ACC.ROLE_MENU;
case COM.ROLE_SYSTEM_MENUITEM: return ACC.ROLE_MENUITEM;
case COM.ROLE_SYSTEM_SEPARATOR: return ACC.ROLE_SEPARATOR;
case COM.ROLE_SYSTEM_TOOLTIP: return ACC.ROLE_TOOLTIP;
case COM.ROLE_SYSTEM_SCROLLBAR: return ACC.ROLE_SCROLLBAR;
case COM.ROLE_SYSTEM_DIALOG: return ACC.ROLE_DIALOG;
case COM.ROLE_SYSTEM_STATICTEXT: return ACC.ROLE_LABEL;
case COM.ROLE_SYSTEM_PUSHBUTTON: return ACC.ROLE_PUSHBUTTON;
case COM.ROLE_SYSTEM_CHECKBUTTON: return ACC.ROLE_CHECKBUTTON;
case COM.ROLE_SYSTEM_RADIOBUTTON: return ACC.ROLE_RADIOBUTTON;
case COM.ROLE_SYSTEM_COMBOBOX: return ACC.ROLE_COMBOBOX;
case COM.ROLE_SYSTEM_TEXT: return ACC.ROLE_TEXT;
case COM.ROLE_SYSTEM_TOOLBAR: return ACC.ROLE_TOOLBAR;
case COM.ROLE_SYSTEM_LIST: return ACC.ROLE_LIST;
case COM.ROLE_SYSTEM_LISTITEM: return ACC.ROLE_LISTITEM;
case COM.ROLE_SYSTEM_TABLE: return ACC.ROLE_TABLE;
case COM.ROLE_SYSTEM_COLUMNHEADER: return ACC.ROLE_TABLECOLUMN;
case COM.ROLE_SYSTEM_OUTLINE: return ACC.ROLE_TREE;
case COM.ROLE_SYSTEM_PAGETABLIST: return ACC.ROLE_TABFOLDER;
case COM.ROLE_SYSTEM_PAGETAB: return ACC.ROLE_TABITEM;
case COM.ROLE_SYSTEM_PROGRESSBAR: return ACC.ROLE_PROGRESSBAR;
case COM.ROLE_SYSTEM_SLIDER: return ACC.ROLE_SLIDER;
}
return role;
}
/* checkWidget was copied from Widget, and rewritten to work in this package */
void checkWidget () {
if (!isValidThread ()) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
if (control.isDisposed ()) SWT.error (SWT.ERROR_WIDGET_DISPOSED);
}
/* isValidThread was copied from Widget, and rewritten to work in this package */
boolean isValidThread () {
return control.getDisplay ().getThread () == Thread.currentThread ();
}
}